2012-01-17 27 views
14

Tôi vừa quan sát hành vi này;Cụm từ thông dụng không khớp với chuỗi rỗng ở chế độ nhiều dòng (Java)

Pattern p1 = Pattern.compile("^$"); 
Matcher m1 = p1.matcher(""); 
System.out.println(m1.matches()); /* true */ 

Pattern p2 = Pattern.compile("^$", Pattern.MULTILINE); 
Matcher m2 = p2.matcher(""); 
System.out.println(m2.matches()); /* false */ 

Nó đánh tôi là kỳ lạ khi tuyên bố cuối cùng là sai. Đây là những gì các tài liệu nói;

Theo mặc định, cụm từ thông dụng^và $ bỏ qua dòng và chỉ kết hợp ở đầu và cuối tương ứng của toàn bộ chuỗi đầu vào. Nếu chế độ MULTILINE được kích hoạt thì^đối sánh ở đầu đầu vào và sau bất kỳ đầu cuối dòng nào ngoại trừ ở cuối đầu vào. Khi ở chế độ MULTILINE $ phù hợp ngay trước một trình kết thúc dòng hoặc kết thúc chuỗi đầu vào. http://docs.oracle.com/javase/1.4.2...

Từ những gì tôi nhận được từ điều này, nó phải khớp? Sau đây làm cho mọi việc trở nên khó hiểu hơn;

Pattern p3 = Pattern.compile("^test$"); 
Matcher m3 = p3.matcher("test"); 
System.out.println(m3.matches()); /* true */ 

Pattern p4 = Pattern.compile("^test$", Pattern.MULTILINE); 
Matcher m4 = p4.matcher("test"); 
System.out.println(m4.matches()); /* true */ 

Vậy đây là gì? Làm thế nào để tôi hiểu được điều này? Tôi hy vọng ai đó có thể làm sáng tỏ điều này, sẽ thực sự được đánh giá cao.

+1

Đây là Java SE 6 (hệ điều hành MacOS X Default) –

+0

Chỉ cần thử nó trên OpenJDK (IcedTea6 1.9.10) và hành vi kỳ lạ cùng nắm giữ. –

+0

Tương tự trên Oracle JRE 7 – Ingo

Trả lời

6

Nếu chế độ MULTILINE được kích hoạt sau đó^phù hợp vào đầu đầu vào và sau khi bất kỳ dòng terminator trừ ở cuối đầu vào.

Vì bạn đang ở cuối đầu vào, ^ không thể khớp ở chế độ nhiều dòng.

Điều này thật đáng ngạc nhiên, thậm chí là kinh tởm, nhưng vẫn theo tài liệu của nó.

+0

Điều này "ngoại trừ ở cuối đầu vào" chỉ đề cập đến "và sau bất kỳ trình kết thúc dòng nào". Vì chúng ta không có terminator dòng, chúng ta đang ở đầu của đầu vào, vì vậy nó phải khớp. – stema

+0

'/^$/m','/^ $/','/\ A \ Z/m', '/ \ A \ Z /', '\ A \ z /', '/ ^/m', '/ $/m' khớp với chuỗi rỗng trong Perl. Đây có phải là vấn đề nền tảng không? Tất cả các tài liệu đều nói cùng một điều. Lạ thật! – sln

+0

@stema Làm thế nào để bạn biết điều này? Ý tôi là, hành vi có vẻ như nó ám chỉ đến việc liệu^có thể phù hợp với tất cả hay không. – Ingo

2

Hãy nhìn một chút kỹ hơn ví dụ thứ hai của bạn:

Pattern p2 = Pattern.compile("^$", Pattern.MULTILINE); 
Matcher m2 = p2.matcher(""); 
System.out.println(m2.matches()); /* false */ 

Vì vậy, bạn có một dòng trong m2, có nghĩa là trống rỗng HOẶC chỉ chứa nhân vật của endline và không có các nhân vật khác. Vì vậy, bạn mô hình, để tương ứng với đường thẳng cho trước, nên chỉ "$" nghĩa là:

// Your example 
Pattern p2 = Pattern.compile("^$", Pattern.MULTILINE); 
Matcher m2 = p2.matcher(""); 
System.out.println(m2.matches()); /* false */ 

// Let's check if it is start of the line 
p2 = Pattern.compile("^", Pattern.MULTILINE); 
m2 = p2.matcher(""); 
System.out.println(m2.matches()); /* false */ 

// Let's check if it is end of the line 
p2 = Pattern.compile("$", Pattern.MULTILINE); 
m2 = p2.matcher(""); 
System.out.println(m2.matches()); /* true */ 
+0

Nó không giải quyết câu hỏi của OP mà ''^$ '' khớp mà không có chế độ 'MULTILINE' nhưng không làm như vậy trong chế độ' MULTILINE'. – anubhava

+0

@anubhava Đó là, vì chúng ta không có sự bắt đầu của chuỗi, nhưng chỉ kết thúc của nó. Theo JDK API: Trong chế độ nhiều dòng, biểu thức^và $ khớp ngay sau hoặc ngay trước, tương ứng, trình kết thúc dòng hoặc kết thúc chuỗi đầu vào.Theo mặc định, các biểu thức này chỉ khớp ở đầu và cuối của toàn bộ chuỗi đầu vào. (http://docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html) Trong một dòng, chúng tôi đang nhận được một chuỗi rỗng và ở chế độ nhiều dòng - trống trình tự. – wanderlust

+0

+1 để là người đầu tiên. Có nghĩa với tôi. –

1

Có vẻ như một lỗi. Nhiều nhất, ở chế độ nhiều dòng, "^" và "$" có thể được hiểu là khớp tại một đường ranh giới nội bộ. Java có thể không có cấu trúc trạng thái biến mở rộng, ví dụ như Perl. Tôi không biết đây có phải là nguyên nhân hay không.

Thực tế là /^test$/m khớp chỉ chứng minh^$ hoạt động ở chế độ nhiều dòng ngoại trừ khi chuỗi trống (trong Java), nhưng kiểm tra chế độ đa dòng rõ ràng cho chuỗi rỗng là lố bịch kể từ khi /^$/ hoạt động.

Testing trong Perl, mọi thứ hoạt động như mong đợi:

if ("" =~ /^$/m ) { print "/^\$/m matches\n"; } 
if ("" =~ /^$/ ) { print "/^\$/  matches\n"; } 
if ("" =~ /\A\Z/m) { print "/\\A\\Z/m matches\n"; } 
if ("" =~ /\A\Z/ ) { print "/\\A\\Z/ matches\n"; } 
if ("" =~ /\A\z/ ) { print "/\\A\\z/ matches\n"; } 
if ("" =~ /^/m ) { print "/^/m  matches\n"; } 
if ("" =~ /$/m ) { print "/\$/m  matches\n"; } 


__END__ 


/^$/m matches 
/^$/  matches 
/\A\Z/m matches 
/\A\Z/ matches 
/\A\z/ matches 
/^/m  matches 
/$/m  matches 
+0

Đồng ý, tôi đã thử nghiệm '/^$/m' và'/^ $/'cho .net, nó cũng hoạt động như mong đợi. – stema

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