Одно из значений "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);
}
}
}
}