2014-02-10 4 views
3

Я читаю учебник Oracle по регулярным выражениям. Я нахожусь по теме Capturing groups. Хотя ссылка отличная, но за исключением того, что скобка представляет собой группу, я нахожу много трудностей в понимании темы. Вот мои недоумения.Регулярные выражения - группы захвата путаницы

  1. Каково значение подсчета групп в выражении?
  2. Что представляют собой группы, не захватывающие захват?

Разработка с примерами будет приятной.

ответ

1

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

(.+)\1 

Путь это работает .+ соответствует любой последовательности символов. Потому что это в скобках, это пойман в группе. \1 является backreference группе захвата 1, поэтому это эквивалент текста, захваченного группой захвата. После небольшого отступа, группа захвата совпадает с первой частью строки, abc. Обратная ссылка \1 теперь эквивалентна abc, поэтому она соответствует второй половине строки. Вся строка теперь сопоставляется, поэтому подтверждается, что первая половина строки соответствует второй половине.


Другое использование обратных ссылок в замене. Скажем, вы хотите заменить все {...} на [...], если текст внутри { и } - это всего лишь цифры. Вы можете легко сделать это с помощью захвата групп и обратные ссылки, используя регулярные выражения

{(\d+)} 

И заменяя, что с [\1].

Регулярное выражение соответствует {123} в строке abc {123} 456 и фиксирует 123 в первой группе захвата. Обратная связь \1 теперь эквивалентна 123, поэтому замена {(\d+)} на abc {123} 456 с [\1] приводит к abc [123] 456.


Причина, по которой группы, не связанные с захватом, существуют потому, что группы в целом имеют больше применений, которые просто захватывают. Регулярное выражение (xyz)+ соответствует строке, целиком состоящей из группы, xyz, повторяющейся, например xyzxyzxyz. Требуется группа, потому что xyz+ соответствует только xy, а затем z повторяется, то есть xyzzzzz. Проблема с использованием групп захвата заключается в том, что они относительно неэффективны по сравнению с группами, не связанными с захватом. Регулярное выражение (?:xyz)+ найдет матч намного раньше, чем (xyz)+, потому что группе не нужно помнить, что это соответствовало.

Надеюсь, это поможет!

+0

Спасибо, Райан. Примеры были очень полезными. Благодаря тонну. – benz

1
  1. Невозможно представить подходящий пример на данный момент, но я предполагаю, что кому-то может потребоваться узнать количество вспомогательных совпадений в RegEx.
  2. Группа 0 всегда является базовым матчем. Я предполагаю, что groupCount() просто позволяет вам узнать, сколько групп захвата вы указали в выражении.
  3. Нехватывающая группа (?:) будет использоваться, чтобы не захватить группу. Ex. если вам нужно проверить, содержит ли строка одно из нескольких слов и не хочет записывать слово в новой группе: (?:hello|hi there) world! == hello|hi there world. Первые матчи «привет мир» или «привет мир», но второй матчи «привет» или «привет мир».
  4. Они могут использоваться как часть множества веских причин, таких как проверка того, является ли число простым или составным. :) Или вы можете просто проверить, чтобы параметр поиска не повторялся, т.е. ^(\d)(?!.*\1)\d+$ гарантирует, что первая цифра уникальна в строке.
+0

Хотя [интересно] (http://codegolf.stackexchange.com/questions/20338/match-strings-whose-length-is-isolated-prime), тестирование простых чисел должно выполняться с целым оператором, а не с регулярным выражением. Это скорее возможность, а не хорошее решение. – nhahtdh

2
  1. Один обычно не количество групп, кроме как знать, какая группа имеет какой номер. Например. ([abc])([def](\d+)) имеет три группы, поэтому я знаю, что они относятся к ним как \1, \2 и \3. Обратите внимание, что группа 3 является внутри 2. Они пронумерованы слева, где они начинают.
  2. Когда поиска с регулярным выражением, чтобы найти что-то в строке, в отличие от сопоставления когда вы убедитесь, что вся строка соответствует теме, группа 0 даст вам только найденную строку, но не тот материал, который был прежде или после него. Представьте, если вы будете иметь пару скобок вокруг всего вашего регулярного выражения. Это не часть общего счета, потому что это действительно не считается группой.
  3. Группы могут использоваться для других целей, кроме как захвата. Например. (foo|bar) будет соответствовать "foo"или"bar". Если вас не интересует содержимое группы, вы можете сделать ее не захватывающей (например: (?:foo|bar) (зависит от диалекта)), чтобы не «использовать» номера, присвоенные группам. Но вы не должны, это просто удобно.
  4. Скажите, что я хочу найти слово, которое начинается и заканчивается тем же письмом: \b([a-z])[a-z]*\1\b\1 будет таким же, как и в первой группе. Конечно, его можно использовать для гораздо более мощных вещей, но я думаю, вы получите эту идею.

(Принятие соответствующих примеров, безусловно, является самой сложной частью.)

Edit: я ответил, когда вопросы были:

  1. Какое значение подсчета групп в выражении?
  2. Существует специальная группа, называемая group-0, что означает все выражение. Метод groupCount() не сообщается. Почему это?
  3. Я не понимаю, что не захватывает группы?
  4. Почему нам нужны обратные ссылки? В чем смысл обратных ссылок?
+0

не могли бы вы прояснить свою точку три? – benz

+1

@benz Скажем, у меня есть регулярное выражение с рядом групп, содержимое которых я хочу использовать. Я заставляю их записывать группы, чтобы я мог использовать их содержимое (в самом регулярном выражении с обратными ссылками ('\ 1' и т. Д.) Или во все, что я использую regex lib (например,' match.GetGroup (1) ')) , Тогда предположим, что у меня есть место, где я хочу соответствовать одному из трех слов, но мне все равно, какой он: '... (?: one | two | three) ...' Я делаю это не захватывающим , чтобы не назначать ему число; только группы, в содержании которых я заинтересован, будут цифры. – Biffen

Смежные вопросы