簡體   English   中英

在正則表達式中使用條件

[英]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報告的總數中。 以(?為開頭的組是純的,不捕獲的組,它們不捕獲文本並且不計入該組的總數。(您將在模式類的方法部分中稍后看到不捕獲的組的示例。)

Java Regex教程

簡短的答案:這沒有任何意義。 問題在於整個片段:

(?(1)\s*)

()創建反向引用,因此您可以重復使用內部匹配的任何文本。 它們還允許您將運算符應用於其中的所有內容(但是在您的示例中未完成)。

表示它之前的項目應該匹配,如果沒有,也可以。 當它出現在之后

(?: MoreTextHere )當您不需要重用匹配的文本時,可用於加速RegExs。 但這仍然沒有任何意義,為什么當您輸入的是HTML時為什么匹配1?

嘗試:

(?:<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>

您從未確切地說過您要匹配的內容,因此,如果此答案不能使您滿意,請解釋一下您要使用RegEx做些什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM