2010-04-25 1523 views
28

http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html正則表達式中的 z和 Z有什麼區別,以及何時以及如何使用它?

\Z The end of the input but for the final terminator, if any 
\z The end of the input 

但到底是什麼在實踐中意味着什麼?你可以給我一個例子,當我使用\ Z或\ Z。

在我的測試中,我認爲"StackOverflow\n".matches("StackOverflow\\z")將返回true,"StackOverflow\n".matches("StackOverflow\\Z")返回false。但實際上兩者都返回假。錯誤在哪裏?

回答

22

「即使\ Z和$只匹配字符串的末尾(當插入符和美元匹配嵌入換行符的選項關閉時),有一個例外:如果字符串以行結尾break,那麼\ Z和$會在換行符之前的位置匹配,而不是在字符串末尾。這個「增強」是由Perl引入的,並且被許多正則表達式複製,包括Java,.NET和PCRE在Perl中,當從文件中讀取一行時,結果字符串將以換行符結束,從文本中讀取一行文本爲「joe」的結果爲字符串joe \ n。^[az] + $和\ A [az] + \ Z將匹配joe

如果您只希望匹配字符串的絕對末尾,請使用\ z(小寫z代替) f大寫字母Z)。 \ A [a-z] + \ z與joe \ n不匹配。 \ z上的換行符,這不是由字符類匹配後匹配。」

http://www.regular-expressions.info/anchors.html

我看這個問題的方法 「的StackOverflow \ n」 .matches( 「StackOverflow的\ Z」)應該返回false,因爲你的模式不包括換行符。

"StackOverflow\n".matches("StackOverflow\\z\\n") => false 
"StackOverflow\n".matches("StackOverflow\\Z\\n") => true 
4

剛纔檢查它。它看起來當Matcher.matches()被調用一樣(比如在你的代碼,在幕後),\ž行爲像\ž。但是,當調用Matcher.find()時,它們的行爲與預期的不同。以下返回true:

Pattern p = Pattern.compile("StackOverflow\\Z"); 
Matcher m = p.matcher("StackOverflow\n"); 
System.out.println(m.find()); 

如果用\ z替換\ Z,它將返回false。

我覺得這有點令人驚訝......

+0

這並不奇怪(因爲我剛剛從接受的答案理解)作爲'\ z'只在字符串的「真實」的最終匹配。由於換行符,'StackOverflow'後你的字符串還沒有完成。 – maaartinus 2014-11-27 10:42:04

0

一樣的Eyal說,它爲查找(),但不匹配()。

這實際上是有道理的。 \ Z錨本身實際上與最終的終止符之前的位置匹配,但是整個正則表達式不匹配,因爲整體而言,它需要匹配整個正在匹配的文本,並且沒有匹配終止符。 (\ Z匹配之前的位置終止符,這是不一樣的事情。)

如果你做了"StackOverflow\n".matches("StackOverflow\\Z.*")你應該沒問題。

+0

\ z(小寫字母z)在換行符之前不匹配,它在換行符後面的最後匹配。 – 2010-04-25 16:07:42

+0

@Jakob:你說得對。我的意思是\ Z,當然 - 那是具有特殊含義的那個。我對這個問題的措辭感到困惑。現在修復。 – Avi 2010-04-25 16:55:45

+0

\ Z(大寫字母)在javadocs定義的最終換行符之前確實匹配。 perl文檔(http://perldoc.perl.org/perlre.html)使其更加清晰:「\ Z \t只匹配字符串末尾或換行符末尾」 – Avi 2010-04-25 16:56:52

0

我覺得這裏主要的問題是matches()的意外行爲,任何匹配都要消耗整個輸入字符串。這兩個示例都失敗了,因爲正則表達式不會消耗字符串末尾的換行符。錨與它無關。

在大多數語言中,正則表達式匹配可能發生在任何地方,消耗全部,部分或全部輸入字符串。 Java有一個方法,Matcher#find(),執行這種傳統類型的匹配。然而,結果是你說你預計的相反:

Pattern.compile("StackOverflow\\z").matcher("StackOverflow\n").find() //false 
Pattern.compile("StackOverflow\\Z").matcher("StackOverflow\n").find() //true 

在第一個例子中,\z需要字符串的結尾匹配,但尾隨換行是在路上。在第二種情況下,\Z匹配字符串之前的換行符。

0

\Z$相同,它匹配字符串的末尾,字符串的末尾可以跟一個換行符。

enter image description here enter image description here

\z字符串的結束相匹配,不能後跟換行符。

enter image description here enter image description here

相關問題