【问题标题】:Parsing (and taking the group) for Regular Expression with repetition用重复解析(并取组)正则表达式
【发布时间】:2011-06-12 22:28:35
【问题描述】:

我尝试使用 java 解析规则并使用 RegEx 读取其中的任何内容,但由于我对 RegEx 非常陌生,因此发现了几个问题。

首先,我尝试用这个RegEx解析一个谓词(我不知道这是否太复杂):"([a-zA-Z]+)\\(([\\?]?[a-zA-Z0-9]+)?(,[\\?]?[a-zA-Z0-9]+)*\\)",我刚刚发现这是完全错误的......谓词应该是这样的(我懒得写完整的表达式),p(), p(?a), p(?a,?b,c,?d)。谓词名称必须是字符串(仅包含字母字符),参数是仅包含字母字符或以 ? 开头的字符串。

这里我发现了两个问题,给定元素p(a,b,c):

  1. 当我循环查看每个组的元素时(使用Matcher),结果只有p(a,b,c)pa,c,我该如何检索@987654330 @也?
  2. 如何在组内不包含,(逗号符号),注意重复时也要包含它?

另外一种情况,当我输入p()时,为什么会得到一个元素为null的组?

知道如何解决这个问题吗?

【问题讨论】:

  • 仅供参考:您的正则表达式实际上非常好。
  • 附带说明,如果您打算做很多复杂的语言匹配,您可能需要考虑使用解析器,例如 ANTLR 或 JavaCC,而不是正则表达式。一个实际的解析器+词法分析器可以比正则表达式更容易地处理更多的事情。

标签: java regex repeat capturing-group


【解决方案1】:

您最长的示例字符串中的“arg”值之一是?b?,它似乎与您的描述不符。删除它,您的正则表达式匹配所有样本,但这仍然给您留下提取单个参数的问题。在 Java 中最简单的方法是将所有参数捕获为一个字符串,然后拆分该字符串以分解各个参数。

正如@Tomalak 所说,您的正则表达式非常好;我唯一能看到的错误是代表第一个参数的组之后的?。它应该控制整个参数字符串,而不仅仅是第一个参数。我的意思是,如果没有 first 参数,那么寻找第二个、第三个等没有意义,是吗?以下是我的做法:

(?:[?]?[a-zA-Z0-9]+(?:,[?]?[a-zA-Z0-9]+)*)?

这将不匹配任何内容、一个参数或多个以逗号分隔的参数,但它不会匹配(例如),a,?a,b,就像您的正则表达式那样。这是 Java 字符串文字形式的完整正则表达式:

"([a-zA-Z]+)\\(((?:\\??[a-zA-Z0-9]+(?:,\\??[a-zA-Z0-9]+)*)?)\\)"

谓词名称在组 #1 中捕获,参数在组 #2 中捕获。如果没有参数,组#2 将包含一个空字符串(不是null)。否则,您可以用逗号分隔各个参数。

顺便说一句,您可以使用反斜杠 (\?) 或方括号 ([?]) 转义大多数元字符;你不需要两者都做。如果它只是一个字符(即,不是像[!.?] 这样的真实字符类的一部分),我建议使用反斜杠。我知道它与 Java 中的字符数相同,但我认为反斜杠使它更具自我记录性。


编辑:这是我使用的代码:

String[] inputs = { "p()", "p(?a)", "p(?a,?b,c,?d)", "p(a,b,c)" };
Pattern p = Pattern.compile(
    "([a-zA-Z]+)\\(((?:\\??[a-zA-Z0-9]+(?:,\\??[a-zA-Z0-9]+)*)?)\\)");

for ( String s : inputs )
{
  Matcher m = p.matcher(s);
  if ( m.matches() )
  {
    System.out.printf("%nFull match: %s%nPredicate name:%n  %s%n",
                      m.group(), m.group(1));
    String allArgs = m.group(2);
    if (allArgs.length() == 0)
    {
      System.out.println("No arguments");
    }
    else
    {
      System.out.println("Arguments:");
      for (String arg : allArgs.split(","))
      {
        System.out.printf("  %s%n", arg);
      }
    }
  }
}

【讨论】:

  • 对不起?b?,这是一个错字...无论如何,你的正则表达式已经很完整了,但我仍然没有得到我需要的结果,使用matcher.group(i)
  • 这并没有给我太多继续。请参阅我的编辑以获取完整的解决方案。
  • 最后我们需要在参数内部进行拆分,最后我也做了同样的事情,谢谢!
【解决方案2】:

这里我发现有两个问题,给定元素 p(a,b,c)

  1. 你不能(轻易地)用正则表达式做这样的事情。 (在 Perl 中,您可以使用一些技巧来做到这一点。)
  2. 类似(?:,(\w+))

另外一种情况,当我输入p()时,为什么会得到一个元素为null的组?

因为应该匹配“参数”的组根本不匹配,因此没有定义。这就是捕获组的工作方式。您可以在比赛结束后根据需要选择/过滤抱怨。

您想为此使用/构造一个适当的解析器,而不仅仅是使用一个正则表达式。

【讨论】:

    【解决方案3】:

    "谓词应该是这样的(我懒得写完整的表达式),p(),p(?a),p(?a,?b?,c,?d)。”

    我想添加评论,但 ie6 给我带来了麻烦。如果你给出更好的解释,我会给你一个解决方案。

    您正在处理的是文本!不要试图把它粉饰成更奢侈的东西。
    “懒惰”并不能解释p(), p(?a), p(?a,?b?,c,?d) 的含义。必须完全理解每一个文本字符/符号。
    正则表达式功能强大,可能非常令人生畏。一个正则表达式(抽象)不能是
    从抽象中推断出来。

    对不起,我只是看不懂参数。我要删除我的帖子...
    (显然,我无法删除它。如果有人可以帮我删除它,谢谢!)

    【讨论】:

    • 好吧...pred := <string> "(" args ")",其中args := "" | <string> otherarg := ("?")? <string>,`other := "," args | ""
    猜你喜欢
    • 2019-10-18
    • 2015-01-29
    • 2015-07-16
    • 2018-04-29
    • 2015-03-13
    • 2011-01-23
    • 2012-11-21
    • 2014-10-28
    • 2015-12-22
    相关资源
    最近更新 更多