REGEX (PCRE) совпадение только если ноль или один раз - PullRequest
0 голосов
/ 11 ноября 2010

У меня следующая проблема.

Давайте возьмем ввод (wikitext)

======hello((my first program)) world======

Я хочу сопоставить слова "привет", "моя первая программа" и "мир" (обратите внимание на пробел).

Но для ввода:

======hello(my first program)) world======

Я хочу сопоставить слова "привет (моя первая программа" и "мир".

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

Это должно быть сделано со свойствами символов юникода, такими как \ p {L}, \ p {S} или \ p {Z}, как описано здесь .

Есть идеи?

Приложение 1

Регулярное выражение должно просто останавливаться перед любым двойным символом или пунктуацией в терминах Юникода, то есть перед любым \ p {S} {2,} или \ p {P} {2,}.

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

Приложение 2

Шаблон должен работать с preg_match(). Я могу себе представить, как мне сначала разделить это. Возможно, он использовал бы какой-то взгляд, я не знаю, я перепробовал все, что мог себе представить.

Использование только preg_match() является обязательным требованием, заданным в текущей реализации лексера. Так должно быть, потому что это естественный способ работы лексеров: они соответствуют последовательностям во входном потоке.

Ответы [ 2 ]

1 голос
/ 11 ноября 2010
return preg_split('/([\pS\pP])\\1+/', $theString);

Результат: http://www.ideone.com/YcbIf

(Необходимо избавиться от пустых строк вручную.)


Редактировать: как preg_match регулярное выражение:

'/(?:^|([\pS\pP])\\1+)((?:[^\pS\pP]|([\pS\pP])(?!\\3))*)/'

взять 2-ю группу захвата, когда она совпадает.Пример: http://www.ideone.com/ErTVA

Но вы могли бы просто потреблять ([\pS\pP])\\1+ и отбрасывать, или, если не совпадает, потреблять (?:[^\pS\pP]|([\pS\pP])(?!\\3))* и записывать, поскольку ваш лексер все равно будет использовать более 1 регулярного выражения?

0 голосов
/ 11 ноября 2010

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

...