2017-05-17 14 views
20

Tôi tìm thấy một regex thú vị trong một dự án Java: "[\\p{C}&&\\S]"khống và Java nhân vật regex lớp: p {C}

Tôi hiểu rằng && có nghĩa là "thiết lập giao", và \S là "non-khoảng trắng", nhưng \p{C} là gì và có thể sử dụng không?

java.util.regex.Pattern documentation không đề cập đến nó. Các chỉ lớp tương tự trên danh sách là \p{Cntrl}, nhưng họ hành xử khác nhau: cả hai đều trận đấu trên ký tự điều khiển, nhưng \p{C} phù hợp hai lần trên các ký tự Unicode trên U + FFFF, chẳng hạn như PILE OF POO:

public class StrangePattern { 
    public static void main(String[] argv) { 

     // As far as I can tell, this is the simplest way to create a String 
     // with code points above U+FFFF. 
     String poo = new String(Character.toChars(0x1F4A9)); 

     System.out.println(poo); // prints `` 
     System.out.println(poo.replaceAll("\\p{C}", "?")); // prints `??` 
     System.out.println(poo.replaceAll("\\p{Cntrl}", "?")); // prints `` 
    } 
} 

Việc đề cập đến chỉ Tôi đã tìm thấy ở bất kỳ đâu là here:

\ p {C} hoặc \ p {Other}: các ký tự điều khiển ẩn và các điểm mã không sử dụng.

Tuy nhiên, \p{Other} dường như không tồn tại trong Java và các điểm mã phù hợp không được sử dụng.

My phiên bản Java thông tin:

$ java -version 
java version "1.8.0_92" 
Java(TM) SE Runtime Environment (build 1.8.0_92-b14) 
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode) 

Bonus câu hỏi: mục đích khả năng của mô hình ban đầu, "[\\p{C}&&\\S]" là gì? Nó xuất hiện trong một phương thức xác nhận một chuỗi trước khi nó được gửi trong một email: nếu mẫu đó được khớp, ngoại lệ với thông báo "Chuỗi không hợp lệ" được nâng lên.

+3

Diễn giải http: // www.unicode.org/reports/tr44/, 'p {C}' có thể là mã kiểm soát, ký tự điều khiển định dạng, điểm mã thay thế, ký tự sử dụng cá nhân, điểm mã không được gán trước hoặc một noncharacter. Đó là vì điều "điểm mã thay thế" (và việc thực hiện một chút của UTF-16 của Java) rằng một đống poo khớp với hai trong số đó. –

Trả lời

16

Chôn xuống trong các tài liệu mẫu dưới Hỗ trợ Unicode, chúng ta thấy như sau:

Lớp này là phù hợp với cấp độ 1 của Unicode Technical Standard #18: Unicode Regular Expression, cộng RL2.1 Canonical tương đương.

...

Categories thể được chỉ định với tiền tố bắt buộc là: Cả hai \ p {L} và \ p {ISL} là loại chữ Unicode. Giống như tập lệnh và chặn, danh mục cũng có thể được chỉ định bằng cách sử dụng từ khóa general_category (hoặc dạng gc ngắn) như trong general_category = Lu hoặc gc = Lu.

Danh mục được hỗ trợ là danh mục của Tiêu chuẩn Unicode trong phiên bản được chỉ định bởi lớp Ký tự. Tên danh mục là các tên được định nghĩa trong Tiêu chuẩn, cả về quy phạm lẫn thông tin.

Từ Unicode Technical Standard #18, chúng tôi thấy rằng C được xác định để phù hợp với bất kỳ giá trị General_Category khác, và rằng sự ủng hộ cho điều này là một phần trong những yêu cầu để lên Level 1 phù hợp. Java triển khai \p{C} vì nó tuyên bố sự phù hợp với Cấp 1 của UTS # 18.


Nó có lẽ nên hỗ trợ \p{Other}, nhưng dường như nó không.

Tệ hơn nữa, nó vi phạm RL1.7, sẽ chuyển qua Level 1 phù hợp, trong đó yêu cầu phù hợp xảy ra bởi thời điểm mã thay vì mã đơn vị:

Để đáp ứng yêu cầu này, một thực hiện trách nhiệm xử lý đầy đủ các mã Unicode điểm, bao gồm các giá trị từ U + FFFF đến U + 10FFFF. Cụ thể, khi sử dụng UTF-16, một chuỗi bao gồm đại diện hàng đầu theo sau bởi đại diện thay thế sẽ được xử lý như một điểm mã đơn trong khớp.

Không nên có trận đấu cho \p{C} trong chuỗi thử nghiệm của bạn, bởi vì chuỗi thử nghiệm của bạn nên được xuất hiện như một điểm mã biểu tượng cảm xúc duy nhất với General_Category = Vì vậy, (Khác Symbol) thay vì là hai người thay thế.

+0

@Hulk: Lá cờ đó dành cho một nhóm lớp ký tự khác, đặc biệt là các lớp được liệt kê trong "Lớp ký tự được xác định trước" và "Lớp ký tự POSIX (chỉ có ở Hoa Kỳ-ASCII)". '\ p {C}' không phải là một trong số đó. – user2357112

3

Theo https://regex101.com/, \ p {C} phù hợp

ký tự điều khiển vô hình và điểm mã không sử dụng

(các \ phải được thoát vì chuỗi java, vì vậy chuỗi \\ p { C} là regex \ p {C})

Tôi đoán đây là 'kiểm tra chuỗi bị tấn công' dưới dạng \ p {C} có thể không bao giờ xuất hiện bên trong chuỗi hợp lệ (ký tự điền), nhưng tác giả nên đã để lại nhận xét như những gì họ đã kiểm tra và những gì họ muốn để kiểm tra thường là 2 thứ khác nhau.

1

Bất kỳ điều gì khác ngoài mã danh mục Unicode hai chữ cái hợp lệ hoặc một chữ cái bắt đầu mã loại Unicode là bất hợp pháp vì Java chỉ hỗ trợ chữ cái đơn và hai chữ cái viết tắt cho các loại Unicode. Đó là lý do tại sao \p{Other} không hoạt động ở đây.

\p{C} phù hợp hai lần trên các ký tự Unicode trên U+FFFF, chẳng hạn như CỌC HÀNH Poo.

Phải. Java sử dụng mã hóa UTF-16 nội bộ cho các ký tự Unicode và được mã hóa như hai mã 16-bit đơn vị (0xD83D 0xDCA9) được gọi là cặp thay thế (high surrogates) và kể từ \p{C} trận đấu mỗi nửa riêng

\p{Cs} hoặc \p{Surrogate}: một nửa cặp thay thế trong mã hóa UTF-16 .

bạn thấy hai kết quả phù hợp trong tập hợp kết quả.

Mục đích có thể có của mẫu gốc, [\\p{C}&&\\S] là gì?

Tôi không thấy một lý do nhiều hợp lệ nhưng có vẻ như nhà phát triển lo lắng về nhân vật trong thể loại Other (như tránh spam goomojies trong chủ đề email) để chỉ đơn giản là cố gắng để ngăn chặn chúng.

+0

Các nguồn cho hai câu lệnh đầu tiên bạn đánh dấu là dấu ngoặc kép là gì? Sẽ rất thú vị vì dường như mâu thuẫn với câu trả lời bình chọn hàng đầu hiện tại http://stackoverflow.com/a/44034552/2513200 – Hulk

Các vấn đề liên quan