2017-02-08 5 views
1

Рассмотрим следующий пример:Regex режим многострочный с возможностью группы пропустить действительные данные

$payload = ' 
ababaaabbb =%= 
ababaaabbb =%= 
ababaa  =%= 
'; 

$pattern = '/^[ab]+\s*(?:=%=)?$/m'; 
preg_match_all($pattern, $payload, $matches); 
var_dump($matches); 

Ожидаемый и фактический результат матча:

"ababaaabbb =%=" 
"ababaaabbb =%=" 
"ababaa  =%=" 

Но если $payload изменено на

$payload = ' 
ababaaabbb =%= 
ababaaabbb =%= 
ababaa  =%'; // "=" sign removed at EOL 

фактический результат:

"ababaaabbb =%=" 
"ababaaabbb =%=" 

, но ожидается, является

"ababaaabbb =%=" 
"ababaaabbb =%=" 
"ababaa  " 

Почему это происходит? Группа (?:=%=)? является необязательной из-за ?, и последняя строка в полезной нагрузке также должна присутствовать в результатах сопоставления.

+1

положить конец линейного якоря внутри необязательной группы: '(?: =% = $)?' –

+0

О, это работает! Но как? '' '' '' '' в многострочном режиме означает «до \ n или EOL», поэтому он должен работать в случае строки «ababaa =%», потому что необязательная часть с «=% =» недопустима, но EOL может быть достигнуто с '' '' '' '', или я могу положить «\ n» в конце. – Alex

+0

Когда необязательная группа выходит из строя (с моим предлагаемым изменением), шаблону не нужно достигать конца строки, чтобы преуспеть, совпадение останавливается в последнем пространстве или в конце a или b, если пробелов нет. –

ответ

1

Посмотрите на текущем графике регулярных выражений:

enter image description here

=%=является факультативным (посмотреть, как ветвь между white space и End of line вилок), но EOL требуется.Это означает, что после одного или нескольких символов a или b, а также ноль или более пробелов, EOL должен произойти. Однако у вас есть =% на вашей третьей строке => НЕТ МАТЧА.

Теперь, когда вы перемещаете $ якорь в необязательной группе:

enter image description here

Конец линии теперь опционально тоже, и матч будет возвращен после согласования 1+ a или b символы и необязательные пробелы.

+0

Спасибо, отличное объяснение! – Alex

+0

:) «Видеть - это верить». –

0

Поскольку последняя строка заканчивается =%, вы должны сделать последние = необязателен и использовать захват группу для ожидаемых данных:

/^([ab]+\s*)(?:=%=?)?$/m 

RegEx Demo

PS: Вашего ожидаемый результат доступный в захваченной группе # 1

+0

Посмотрите на последнюю строку ожидаемого результата. –

+0

Нет, потому что только '' '=% =' '' или ничего не должно быть сопоставлено. – Alex

+0

Ваша последняя строка заканчивается '=%', поэтому почему эта строка включена в ожидаемый результат? – anubhava

0

Группа (?:=%=)? является необязательной в вашем регулярном выражении. То, что не означает, что каждая часть этой группы также является необязательной.

Ваше регулярное выражение работает только тогда, когда он видит строку a с и b с, дополнительным пробелом, а затем либо (1) =%= и конец строки или (2) только в конце строки. Он не будет работать, если он увидит строку a s и b s, пробел, а затем ничего, кроме точно =%= или конец строки. Итак, =% не будет работать.

Чтобы выполнить то, что вы, видимо, хотите сделать, вам нужно сделать второй = необязательными, например, так:

$pattern = '/^[ab]+\s*(?:=%=?)?$/m'; 
// see the additional ? here^ 

Но, похоже, вы не хотите, =%вообще в этом сценарии , что означает, что вам нужно, чтобы получить более творческие еще:

$pattern = '/^[ab]+\s*(?:(?:=%=)?$|(?==%$))/m'; 

Demo.

+0

В моем случае необязательная часть '' '=% =' '', '' '=%' '', '' '=' '' и ничего. Я удивлен вашим «Это не сработает, если он увидит строку' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' . ". Я подумал, что необязательная группа - если она не соответствует - просто «пропущена» в EOL, соответствует «' '' '' '', что приводит ко всем строкам типа «aabb =%». – Alex

+0

Ну, если вы также хотите разрешить просто '=' в конце строки, измените мой второй пример на '$ pattern = '/^[ab] + \ s * (?: (?: =% =)? $ | (? ==%? $))/m '; '(обратите внимание на'? 'после'% '). Необязательные группы * * пропускаются, если они не совпадают, но весь шаблон все равно должен совпадать. Представьте, если вы удалите необязательную группу из вашего регулярного выражения, оставив '/^[ab] + \ s * $/m'. Это не соответствует 'ababaa =%', потому что между пробелами и концом строки есть что-то ('=%'). –