2009-02-03 24 views
0

如使用条件:
文字:在正则表达式

<!-- Nav bar -->

<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.

+0

这是什么书? – 2009-02-03 10:41:18

+0

“在10分钟内教自己正则表达式” – JSON 2009-02-03 14:13:05

+0

对于阅读此问题的任何人,请注意,正则表达式`java.util.regex`的标准Java包不支持正则表达式中的条件。 – 2015-10-25 07:52:28

回答

3

语法无误。奇怪的(?....)设置了一个条件。这是if ... then语句的正则表达式语法。 (1)是正则表达式开始处的捕获组的返回引用,它与html标记匹配,如果有一个标记,因为该捕获组是可选的。由于对捕获到的标签的反向引用遵循正则表达式的“if”部分,因此它正在做的是确保在尝试匹配最后一个标签之前捕获到一个开头的标签。一个非常聪明的方式使两个标签都是可选的,但是在第一个标签存在时强制这两个标签。这就是它能够匹配示例文本中的所有行,即使它们中的一些仅具有<img>标签。

至于为什么它会在您的情况下抛出异常,很可能您使用的正则表达式的风格不支持条件。并不是全部。

编辑:这里的正则表达式中的条件句很好的参考:http://www.regular-expressions.info/conditional.html

1

难道是一个非捕获组,如下所述:

还有一个特殊的群体,群 0,它总是代表整个 表达式。该群组不包括 中由groupCount报告的总数。 组用(开头?是不 捕捉文本和不计入 数占集团总。(你会在的的 部分方法在后面看到的例子非捕获组 纯, 非捕获组模式类)

Java Regex Tutorial

1

简短的回答:这并不意味着什么。问题就出在这整个片段:

(?(1)\s*) 

()创建一个反向引用,所以你可以重用内匹配任何文本。他们还允许您将运算符应用于其中的所有内容(但这不是在您的示例中完成的)。

表示它之前的项目应该匹配,但如果它不存在则也可以。这只是当它出现时没有意义后

(?:MoreTextHere) 可以用来当你不需要重复使用匹配的文本,以加快RegExs但仍然没有按”吨真的是有意义的,为什么当你输入HTML匹配1

尝试:?

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

你从来没有说过什么你试图匹配,所以如果这个答案不能满足你,请解释你想用RegEx做什么

+1

正如Bryan所说,语法对于支持条件的正则表达式是正确的,但Java不支持。 – 2009-02-03 10:34:03

3

什么你看到的是一个条件结构,为布赖恩说,和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)); 
}