[英]Using Condition in Regular Expressions
資源:
<TD>
<A HREF="/home"><IMG SRC="/images/home.gif"></A>
<IMG SRC="/images/spacer.gif">
<A HREF="/search"><IMG SRC="/images/search.gif"></A>
<IMG SRC="/images/spacer.gif">
<A HREF="/help"><IMG SRC="/images/help.gif"></A>
</TD>
正則表達式:
(<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>(?(1)\s*</[Aa]>)
結果:
<A HREF="/home"><IMG SRC="/images/home.gif"></A>
<IMG SRC="/images/spacer.gif">
<A HREF="/search"><IMG SRC="/images/search.gif"></A>
<IMG SRC="/images/spacer.gif">
<A HREF="/help"><IMG SRC="/images/help.gif"></A>
“?(1)”是什么意思?
當我在Java中運行它時,它將導致異常:java.util.regex.PatternSyntaxException,無法識別“?(1)”。
書中的解釋是:
This pattern requires explanation. (<[Aa]\\s+[^>]+>\\s*)? matches an opening <A> or <a> tag (with any attributes that may be present), if present (the closing ? makes the expression optional). <[Ii][Mm][Gg]\\s+[^>]+> then matches the <IMG> tag (regardless of case) with any of its attributes. (?(1)\\s*</[Aa]>) starts off with a condition: ?(1) means execute only what comes next if backreference 1 (the opening <A> tag) exists (or in other words, execute only what comes next if the first <A> match was successful). If (1) exists, then \\s*</[Aa]> matches any trailing whitespace followed by the closing </A> tag.
語法正確。 看起來很奇怪(?....)設置了條件。 這是if ... then語句的正則表達式語法。 (1)是對正則表達式開頭的捕獲組的反向引用,如果有一個,則匹配html <a>標記,因為該捕獲組是可選的。 由於對捕獲到的標記的反向引用是在正則表達式的“ if”部分之后進行的,因此它的工作是確保在嘗試與結束標記匹配之前捕獲了一個開始的<a>標記。 一種使兩個標簽都可選的聰明方法,但是當第一個標簽存在時將它們都強制。 這樣,即使其中一些僅帶有<img>標記,它也能夠匹配示例文本中的所有行。
至於為什么在您的情況下引發異常,您使用的正則表達式很可能不支持條件語句。 並非全部。
編輯:這是對正則表達式中條件的良好參考: http : //www.regular-expressions.info/conditional.html
正如Bryan所說,您正在查看的是一個條件構造,而Java不支持它們。 緊接在問號后面的帶括號的表達式實際上可以是任何零寬度的斷言,例如向前或向后查找,而不僅僅是對捕獲組的引用。 (為了避免混淆,我更喜歡稱其為后斷言 。 后向引用與捕獲組所做的相同,但是反向斷言只是斷言捕獲組已匹配某項 。)
多年前,當我在Perl上工作時,我就了解了條件條件,但是我從來沒有錯過Java。 例如,在這種情況下,一個簡單的替換就可以解決問題:
(?i)<a\s+[^>]+>\s*<img\s+[^>]+>\s*</a]>|<img\s+[^>]+>
條件版本的一個優點是,您可以使用一個捕獲組來捕獲IMG標簽:
(?i)(<a\s+[^>]+>\s*)?(<img\s+[^>]+>)(?(1)\s*</a>)
在替代版本中,每個替代方案都必須具有捕獲組,但這在Java中不像在Perl中那樣重要,因為它具有所有內置的正則表達式魔術。 這是我在Java中選擇IMG標簽的方法:
Pattern p = Pattern.compile(
"<a\\s+[^>]+>\\s*(<img\\s+[^>]+>)\\s*</a>|(<img\\s+[^>]+>)"
Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(s);
while (m.find())
{
System.out.println(m.start(1) != -1 ? m.group(1) : m.group(2));
}
可能是此處所述的非捕獲組:
還有一個特殊的組,組0,它始終代表整個表達式。 該組不包括在groupCount報告的總數中。 以(?為開頭的組是純的,不捕獲的組,它們不捕獲文本並且不計入該組的總數。(您將在模式類的方法部分中稍后看到不捕獲的組的示例。)
簡短的答案:這沒有任何意義。 問題在於整個片段:
(?(1)\s*)
()創建反向引用,因此您可以重復使用內部匹配的任何文本。 它們還允許您將運算符應用於其中的所有內容(但是在您的示例中未完成)。
? 表示它之前的項目應該匹配,如果沒有,也可以。 當它出現在(之后
(?: MoreTextHere )當您不需要重用匹配的文本時,可用於加速RegExs。 但這仍然沒有任何意義,為什么當您輸入的是HTML時為什么匹配1?
嘗試:
(?:<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>
您從未確切地說過您要匹配的內容,因此,如果此答案不能使您滿意,請解釋一下您要使用RegEx做些什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.