Регулярное выражение не жадный жадный - PullRequest
7 голосов
/ 29 октября 2008

У меня есть следующий текст

tooooooooooooon

Согласно этой книге, которую я читаю, когда ? следует после любого квантификатора, он становится не жадным.

Мое регулярное выражение to*?n все еще возвращается tooooooooooooon.

Он должен вернуть ton не так ли?

Есть идеи, почему?

Ответы [ 5 ]

46 голосов
/ 29 октября 2008

Регулярное выражение может соответствовать только фрагменту текста, который действительно существует.

Поскольку подстрока 'ton' не существует нигде в вашей строке, она не может быть результатом совпадения. Совпадение вернет только подстроку исходной строки

РЕДАКТИРОВАТЬ: для ясности, если вы использовали строку ниже, с дополнительным 'n'

toooooooonoooooon

это регулярное выражение (которое не указывает 'o's)

t.*n

будет соответствовать следующему (максимально возможное количество символов перед 'n')

toooooooonoooooon

но регулярное выражение

t.*?n

будет соответствовать только следующему (как можно меньше символов перед 'n')

toooooooon
5 голосов
/ 29 октября 2008

Регулярное выражение всегда стремится соответствовать.

Ваше выражение говорит это:

A 't', followed by *as few as possible* 'o's, followed by a 'n'.

Это означает, что любые необходимые o будут совпадать, потому что в конце есть 'n', которого хочет достичь выражение. Соответствие всем требованиям - это единственная возможность добиться успеха.

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

Regex всегда старается соответствовать. Единственное, что вы делаете в этом случае, - это замедляет работу вашего парсера, возвращая его обратно в узел /o*?/. Один раз за каждый 'o' в "tooooon". Принимая во внимание, что при нормальном сопоставлении с первого раза может потребоваться столько 'o' с, сколько возможно. Поскольку следующий элемент для сопоставления - 'n', который не будет сопоставлен с 'o', нет смысла пытаться использовать минимальное сопоставление. На самом деле, когда нормальное сопоставление не удается, это может занять некоторое время, чтобы оно не сработало. Он должен возвращаться через каждые 'o', пока не останется ни одного, чтобы вернуться назад. В этом случае я бы использовал максимальное совпадение /to*+n/. 'o' примет все, что сможет, и никогда не вернет ничего. Это сделало бы его таким, чтобы при сбое он быстро выходил из строя.

Минимальное повторное RE:

'toooooon' ~~ /to*?n/

 t  o  o  o  o  o  o  n       
{t}                           match [t]
[t]                           match [o] 0 times
[t]<n>                        fail to match [n] -> retry [o]
[t]{o}                        match [o] 1 times
[t][o]<n>                     fail to match [n] -> retry [o]
[t][o]{o}                     match [o] 2 times
[t][o][o]<n>                  fail to match [n] -> retry [o]

. . . .

[t][o][o][o][o]{o}            match [o] 5 times
[t][o][o][o][o][o]<n>         fail to match [n] -> retry [o]
[t][o][o][o][o][o]{o}         match [o] 6 times
[t][o][o][o][o][o][o]{n}      match [n]

Обычный RE успешно:

(ПРИМЕЧАНИЕ: аналогично для максимального RE)

'toooooon' ~~ /to*n/

 t  o  o  o  o  o  o  n       
{t}                           match [t]
[t]{o}{o}{o}{o}{o}{o}         match [o] 6 times
[t][o][o][o][o][o][o]{n}      match [n]

Отказ минимального RE:

'toooooo' ~~ /to*?n/

 t  o  o  o  o  o  o

. . . .

. . . .

[t][o][o][o][o]{o}            match [o] 5 times
[t][o][o][o][o][o]<n>         fail to match [n] -> retry [o]
[t][o][o][o][o][o]{o}         match [o] 6 times
[t][o][o][o][o][o][o]<n>      fail to match [n] -> retry [o]
[t][o][o][o][o][o][o]<o>      fail to match [o] 7 times -> match failed

Сбой нормального RE:

'toooooo' ~~ /to*n/

 t  o  o  o  o  o  o       
{t}                           match [t]
[t]{o}{o}{o}{o}{o}{o}         match [o] 6 times
[t][o][o][o][o][o][o]<n>      fail to match [n] -> retry [o]
[t][o][o][o][o][o]            match [o] 5 times
[t][o][o][o][o][o]<n>         fail to match [n] -> retry [o]

. . . .

[t][o]                        match [o] 1 times
[t][o]<o>                     fail to match [n] -> retry [o]
[t]                           match [o] 0 times
[t]<n>                        fail to match [n] -> match failed

Отказ Max RE:

'toooooo' ~~ /to*+n/

 t  o  o  o  o  o  o
{t}                           match [t]
[t]{o}{o}{o}{o}{o}{o}         match [o] 6 times
[t][o][o][o][o][o][o]<n>      fail to match [n] -> match failed
4 голосов
/ 29 октября 2008

регулярные выражения пытаются сопоставить все в них. Поскольку для совпадения есть не меньше «о», чем у каждого «о», все совпадает. Кроме того, потому что вы используете o *? вместо о +? Вы не требуете присутствия o.

Пример, в Perl

$a = "toooooo";
$b = "toooooon";

if ($a =~ m/(to*?)/) {
        print $1,"\n";
}
if ($b =~ m/(to*?n)/) {
        print $1,"\n";
}

~>perl ex.pl
t
toooooon
2 голосов
/ 29 октября 2008

Строка, в которой вы ищете (как бы стог сена) не содержит подстроку "ton".

Однако он содержит подстроку «tooooooooooooon».

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