Используя регулярные выражения, как найти шаблон, окруженный двумя другими шаблонами, не включая окружающие строки? - PullRequest
4 голосов
/ 10 октября 2008

Я хочу использовать регулярные выражения (совместимые с Perl), чтобы иметь возможность найти шаблон, окруженный двумя другими шаблонами, но не включать строки, соответствующие окружающим шаблонам, в совпадении.

Например, я хочу иметь возможность находить вхождения строк вроде:

Foo Bar Baz

Но только в совпадении есть средняя часть:

Бар

Я знаю, что это возможно, но я не помню, как это сделать.

Ответы [ 4 ]

7 голосов
/ 10 октября 2008

Скобки определяют группировки.

"Foo (Bar) Baz"

Пример

~> cat test.pl
$a = "The Foo Bar Baz was lass";

$a =~ m/Foo (Bar) Baz/;

print $1,"\n";
~> perl test.pl
Bar
4 голосов
/ 11 октября 2008

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

Foo\s+(Bar)\s+Baz

Это не то же самое, что не включать окружающий текст в совпадение. Это, вероятно, не имеет значения, если все, что вы хотите сделать, - это извлечь "Bar", но будет иметь значение, если вы сопоставляете одну и ту же строку несколько раз и хотите продолжить с того места, где остановилось предыдущее соответствие.

Осмотр будет работать в некоторых случаях. Предложение Томалака:

(?<=Foo\s)Bar(?=\sBaz)

работает только для просмотра с фиксированной шириной (по крайней мере, в Perl). Начиная с Perl 5.10, утверждение \K может использоваться для эффективного обеспечения просмотра переменной ширины:

Foo\s+\KBar(?=\s+Baz)

, который должен быть способен выполнять то, о чем вы просили во всех случаях, но потребует, чтобы вы реализовали это в Perl 5.10.

Хотя это было бы удобно, для завершения сопоставленного текста нет эквивалента \K, поэтому вам нужно использовать упреждающий просмотр.

4 голосов
/ 10 октября 2008

Использование lookaround :

(?<=Foo\s)Bar(?=\sBaz)

Это будет соответствовать любому «бару», которому предшествует «Foo», а затем «Baz», разделенные одним пробелом. «Foo» и «Baz» не будут частью финального матча.

2 голосов
/ 10 октября 2008

$ string = ~ m / Foo (Bar) Baz /

$ 1

Это может быть не совсем то, что вы хотите, поскольку матч по-прежнему "Foo Bar Baz". Но он показывает вам, как просто получить интересующую вас часть. В противном случае вы можете использовать lookahead и lookbehind, чтобы получить совпадение без использования символов ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...