ожидаемое поведение расширенного регулярного выражения posix: (() | abc) xyz - PullRequest
2 голосов
/ 17 сентября 2009

На моем компьютере с OS X 10.5.8, используя функции regcomp и regexec C для соответствия расширенному регулярному выражению "(() | abc) xyz", я нахожу совпадение для строки "abcxyz", но только от смещения 3 до смещение 6. Я ожидал, что вся строка будет сопоставлена, и я увижу субматч для начальной части строки «abc».

Когда я пытаюсь использовать тот же шаблон и текст с awk на той же машине, он показывает совпадение для всей строки, как я и ожидал.

Я ожидаю, что мой ограниченный опыт работы с регулярными выражениями может быть проблемой. Может кто-нибудь объяснить, что происходит? Является ли мое регулярное выражение допустимым? Если так, то почему он не совпадает со всей строкой?

Я понимаю, что "((abc) {0,1}) xyz" можно использовать в качестве альтернативы, но интересующий образец автоматически генерируется из другого формата шаблона, и исключение случаев "()" является дополнительной работой Я хотел бы избежать, если это возможно.

Для справки, флаги, которые я передаю regcomp, состоят только из REG_EXTENDED. Я передаю пустой набор флагов (0) в regexec.

Ответы [ 3 ]

2 голосов
/ 26 сентября 2009

Стандарт POSIX гласит:

9.4.3 Специальные символы ERE

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

.[\(

<period>, <left-square-bracket>, <backslash> и <left-parenthesis> должны быть специальными, за исключением случаев, когда они используются в выражении в скобках (см. RE выражение в скобках). За пределами выражения в скобках <left-parenthesis>, за которым сразу следует <right-parenthesis>, дает неопределенные результаты.

То, что вы видите, является результатом вызова неопределенного поведения - все идет.

Если вам нужны надежные, переносимые результаты, вам придется исключить пустые нотации '()'.

0 голосов
/ 17 сентября 2009

Попробуйте (abc|())xyz - Могу поспорить, это даст одинаковый результат в обоих местах. Я могу только предположить, что версия C пытается сопоставить xyz везде, где может, и если это не удается, она пытается сопоставить abcxyz везде, где может (но, как вы видите, это не дает сбоя, поэтому мы никогда возиться с частью "abc"), тогда как awk должен использовать свой собственный движок регулярных выражений, который работает так, как вы ожидаете.

Ваше регулярное выражение действительно. Я думаю, что проблема либо в том, что а) POSIX не очень ясно понимает, как должно работать регулярное выражение, либо б) awk не использует регулярные выражения, совместимые с 100% POSIX (возможно, потому что кажется, что OS X поставляется с более оригинальной версией awk). Независимо от того, какая это проблема, она, вероятно, вызвана тем, что это в некотором роде крайний случай, и большинство людей не стали бы писать регулярное выражение таким образом.

0 голосов
/ 17 сентября 2009

Если вы перебираете все совпадения и не получаете [3,6) и [0,6), тогда есть ошибка. Я не уверен, какой мандат posix, насколько порядок, в котором возвращаются совпадения.

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