Разбор (и взятие группы) для регулярного выражения с повторением - PullRequest
2 голосов
/ 13 июня 2011

Я пытался разобрать правило, используя 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), p, a и ,c, как я могу получить b также?
  2. Как не включать , (знак запятой) внутри группы, обратите внимание, что повторение должно также включать его?

В другом случае, когда я вводил p(), почему он получил группу, в которой элемент null?

Есть идеи, как это исправить?

Ответы [ 3 ]

1 голос
/ 13 июня 2011

Одно из значений "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);
      }
    }
  }
}
0 голосов
/ 13 июня 2011

"Предикат должен выглядеть примерно так (мне лень писать полное выражение), p (), p (? A), p (? A,? B?, C,? D)."

Я хотел добавить комментарий, но ie6 доставляет мне неприятности. Если вы дадите лучшее объяснение, я дам вам решение.

То, с чем вы имеете дело, это текст! Не пытайтесь побелить его как нечто более экстравагантное.
Быть ленивым не объясняет, что означает p(), p(?a), p(?a,?b?,c,?d). Каждый текстовый символ / символ должен быть полностью понят.
Regex является мощным и может быть чрезвычайно сложным. Регулярные формулы (абстракция) не могут быть
выведено из абстракции.

Извините, я просто не могу понять параметры. Я собираюсь удалить свой пост ...
(Очевидно, я не могу удалить это. Если кто-то может удалить это для меня, спасибо!)

0 голосов
/ 13 июня 2011

Здесь я обнаружил две проблемы, учитывая элемент p (a, b, c)

  1. Вы не можете (легко) делать такие вещи с помощью регулярных выражений.(В Perl вы можете использовать некоторые приемы, чтобы сделать это.)
  2. С чем-то вроде (?:,(\w+))

Другой случай, когда я ввожу p (), почемуполучил ли он группу, в которой элемент имеет значение null?

Поскольку группы, которые должны соответствовать «параметрам», вообще не совпадают, то есть не определяются.Вот как работают группы захвата.Вы можете выбрать / отфильтровать ныть, как только захотите после матча.

Вы хотите использовать / создать для этого подходящий синтаксический анализатор, а не просто использовать одно регулярное выражение.

...