正则表达式的普通英语解释

6
我是一名有用的助手,可以翻译文本。

我正在开发一个新的Java项目,因此正在阅读已经存在的代码。在代码的一个非常重要的部分中,我发现了以下正则表达式,但我无法确定它们的作用。有人能用通俗易懂的语言解释一下吗?

1)

 [^,]*|.+(,).+

2)

(\()?\d+(?(1)\))

1
第二个在“Pattern”中无法编译。可能漏了一个反斜杠?“(?”部分看起来很奇怪。 - BalusC
同意(?看起来非常奇怪。问号可能会在不使用反斜杠的情况下逃脱'('。这是我能想到的唯一方法,它才能工作。 - adhanlon
也许它应该是非捕获的 '(?:'。 - Stephen
1
@BalusC:这是条件语句,在Java中不支持。请看我的回答。 - polygenelubricants
2
这个项目最初是用Java编写的吗? - Alan Moore
3个回答

17

下次您需要解释一个正则表达式时,可以使用Rick Measham的以下explain.pl服务:

Regex: [^,]*|.+(,).+

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  [^,]*                    any character except: ',' (0 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
 |                        OR
--------------------------------------------------------------------------------
  .+                       any character except \n (1 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    ,                        ','
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  .+                       any character except \n (1 or more times
                           (matching the most amount possible))

Regex: (\()?\d+(?(1)\))

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (                        group and capture to \1 (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    \(                       '('
--------------------------------------------------------------------------------
  )?                       end of \1 (NOTE: because you're using a
                           quantifier on this capture, only the LAST
                           repetition of the captured pattern will be
                           stored in \1)
--------------------------------------------------------------------------------
  \d+                      digits (0-9) (1 or more times (matching
                           the most amount possible))
--------------------------------------------------------------------------------
  (?(1)                    if back-reference \1 matched, then:
--------------------------------------------------------------------------------
    \)                       ')'
--------------------------------------------------------------------------------
   |                        else:
--------------------------------------------------------------------------------
                             succeed
--------------------------------------------------------------------------------
  )                        end of conditional on \1

链接


关于条件语句的注释

JAVA不支持条件语句!针对第二个模式的无条件正则表达式可能是:

\d+|\(\d+\)

即非零数字的重复,带或不带括号。

链接


模式深入分析

这是第一个模式的测试工具。

    import java.util.regex.*;
    //...

    Pattern p = Pattern.compile("[^,]*|.+(,).+");
    String[] tests = {
        "",       // [] is a match with no commas
        "abc",    // [abc] is a match with no commas
        ",abc",   // [,abc] is not a match
        "abc,",   // [abc,] is not a match
        "ab,c",   // [ab,c] is a match with separating comma
        "ab,c,",  // [ab,c,] is a match with separating comma
        ",",      // [,] is not a match
        ",,",     // [,,] is not a match
        ",,,",    // [,,,] is a match with separating comma
    };
    for (String test : tests) {
        Matcher m = p.matcher(test);
        System.out.format("[%s] is %s %n", test,
            !m.matches() ? "not a match"
            : m.group(1) != null
               ? "a match with separating comma"
               : "a match with no commas"
        );
    }

结论

  • 为了匹配成功,字符串必须符合以下两种情况之一:
    • 不包含逗号(可能为空字符串)
    • 包含逗号,且逗号分隔出两个非空字符串
  • 在匹配成功时,\1 可以用于区分这两种情况

下面是一个类似的测试框架,用于第二个模式,重写而不使用条件语句(Java 不支持条件语句):

    Pattern p = Pattern.compile("\\d+|(\\()\\d+\\)");
    String[] tests = {
        "",       // [] is not a match
        "0",      // [0] is a match without parenthesis
        "(0)",    // [(0)] is a match with surrounding parenthesis
        "007",    // [007] is a match without parenthesis
        "(007)",  // [(007)] is a match with surrounding parenthesis
        "(007",   // [(007] is not a match
        "007)",   // [007)] is not a match
        "-1",     // [-1] is not a match
    };
    for (String test : tests) {
        Matcher m = p.matcher(test);
        System.out.format("[%s] is %s %n", test,
            !m.matches() ? "not a match"
            : m.group(1) != null
               ? "a match with surrounding parenthesis"
               : "a match without parenthesis"
        );
    }

如先前所述,这将匹配一个非零数量的数字,可能被括号包围(\1 能够区分两者)。


哇,我不知道那个网站。看起来很棒。这个程序可以处理多么“复杂”的问题? - ggfan
@ggfan:这只是机械翻译。覆盖所有语法可能并不那么难。对于机器来说,正则表达式并不那么“混乱”。 - polygenelubricants
1
如果你发现自己经常需要做这种事情,那么你可能想要投资于RegexBuddy。它会告诉你如何(以及是否)在你选择的语言/风格中使用正则表达式,而不仅仅是Perl(它支持Java没有的许多功能)。http://www.regexbuddy.com/ - Alan Moore

9

1)

[^,]* means any number of characters that are not a comma
.+(,).+ means 1 or more characters followed by a comma followed by 1 or more characters
|  means either the first one or the second one

2)

(\()? means zero or one '('  note* backslash is to escape '('
\d+ means 1 or more digits
(?(1)\)) means if back-reference \1 matched, then ')' note* no else is given

请注意,括号用于捕获正则表达式中的某些部分,但是如果它们通过反斜杠进行转义,则不会捕获


1
(?是if-then-else条件语句,不被Java支持。请看我的回答。 - polygenelubricants
整个正则表达式的英文摘要也会很有用。 - earlNameless

-1

1)任何不以逗号开头的东西,或者在其中包含逗号的东西。

2)任何以1结尾且在括号内的数字,可能在数字之前关闭括号并再次打开。


@AlanMoore:除了这不是一个工具生成的响应之外,这与polygenelubricants的结论有何不同? - eKek0
1)[^,]*不是指“任何不以逗号开头的东西”,这个应该是[^,].*(除了换行符)。相反,[^,]*指的是“任何不包含逗号的东西”。 2)正如其他答案中所指出的,(?(1)...)部分是一个有条件的表达式(在Java中缺失),而不是一组分组为1的字符。请参见http://www.regular-expressions.info/conditional.html。 - Christian Semrau
@poly的回答还包括对两个正则表达式的彻底分析,这与你的分析非常不同。特别是,如果至少有一个逗号,第一个正则表达式匹配以逗号开头的字符串。我怀疑它的目的是确定一个字符串是否表示单个项目或逗号分隔的项目列表。 - Alan Moore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接