Это нарушает принцип «крайнего левого»? - PullRequest
3 голосов
/ 27 июня 2010

Я пытаюсь написать регулярное выражение для распознавания одной строки текста с подчеркиванием (_), распознаваемым как символ продолжения строки. Например, «foo_ \ nbar» следует рассматривать как одну строку, потому что «foo» заканчивается подчеркиванием. Я пытаюсь:

$txt = "foo_\nbar";
print "$&\n" if $txt =~ /.*(_\n.*)*/;

Однако, это только для печати:

foo_

Кажется, это нарушает правило "самого длинного" для регулярных выражений Perl!

Интересно, если я уберу последнюю звездочку (*) в регулярном выражении, т. Е .:

$txt = "foo_\nbar";
print "$&\n" if $txt =~ /.*(_\n.*)/;

it делает печать:

foo_
bar

Но мне нужно, чтобы звезда распознала продолжения "0 или более"!

Что я делаю не так?

Ответы [ 3 ]

6 голосов
/ 27 июня 2010

Почему это происходит, объяснил @ysth.Чтобы исправить это, вы можете использовать следующее регулярное выражение:

/([^_\n]|_.)*/s
5 голосов
/ 27 июня 2010

Perl не делает «крайний левый»;вместо этого каждая особенность регулярных выражений имеет четко определенный образ действий.Ваш начальный * будет совпадать столько раз, сколько возможно, до тех пор, пока остальное регулярное выражение может совпадать вообщеЧтобы предотвратить проглатывание _, сделайте что-то вроде:

/(.*(?!(?<=_)\n)_\n)*.*/
1 голос
/ 28 июня 2010

Существует два основных варианта дизайна регулярных выражений:

POSIX определяет самый левый-самый длинный аромат. Например: изменение любого «a | b» на «b | a» ничего не дает для полного соответствия.

PERL определяет смещенный влево аромат. Каждый «a | b» проверяет левую ветвь «a», и если это может совпадать, то «b» никогда не проверяется Таким образом, «a | b» редко совпадает с «b | a». Здесь a * похоже на () | a | aa | aaa | aaaa | ...

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