您最长的示例字符串中的“arg”值之一是?b?
,它似乎与您的描述不匹配。删除它,您的正则表达式匹配所有样本,但这仍然给您留下提取单个参数的问题。在 Java 中做到这一点的最简单方法是将所有参数捕获为一个字符串,然后拆分该字符串以分解各个参数。
正如@Tomalak 所说,您的正则表达式非常好;我唯一能看到的错误是在?
代表第一个参数的组之后。它应该控制整个参数字符串,而不仅仅是第一个参数。我的意思是,如果没有第一个论点,那么寻找第二个、第三个等就没有意义了,是吗?这是我的做法:
(?:[?]?[a-zA-Z0-9]+(?:,[?]?[a-zA-Z0-9]+)*)?
这将不匹配任何内容,或者一个参数,或者几个用逗号分隔的参数,但它不会匹配(例如),a
or ,?a,b
,就像你的正则表达式那样。这是 Java 字符串文字形式的完整正则表达式:
"([a-zA-Z]+)\\(((?:\\??[a-zA-Z0-9]+(?:,\\??[a-zA-Z0-9]+)*)?)\\)"
谓词名称在组 #1 中捕获,参数在组 #2 中捕获。如果没有参数,组 #2 将包含一个空字符串(不是 a 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);
}
}
}
}