Компилятор регулярных выражений R работает по-разному для данного регулярного выражения - PullRequest
4 голосов
/ 26 мая 2020

Я работал над уточнением этого ответа; и выяснил, что приведенное ниже регулярное выражение не работает должным образом (в соответствии с его значением) в R.

 +?on.*$

Согласно моему пониманию регулярного выражения, указанное выше регулярное выражение соответствует:

лениво пробел один или несколько раз, затем on с последующим любым (кроме новой строки) до конца.

INPUT:

Posted by ondrej on 29 Feb 2020.
Posted by ona'je on 29 Feb 2020.

ВЫХОД (по моему мнению, если вышеуказанный шаблон регулярного выражения в тестовой строке заменен на "")

Posted by
Posted by 

И когда я пытаюсь его проверить in python (реализация здесь) , javascript и java (реализация здесь) ; Я получаю ожидаемый результат.

const myString = "Posted by ondrej on 29 Feb 2020.\nPosted by ona'je on";

console.log(myString.replace( new RegExp(" +?on.*$","gm"),""));

С другой стороны, если я пытаюсь реализовать то же регулярное выражение в R (реализация здесь) ; Я получаю результат как

Posted by ondrej
Posted by ona'je

, и это неожиданно.

Сомнение

Я подумал, что, возможно, парсер регулярных выражений для R работает по-другому (возможно, справа налево). Я прочитал документацию о том, как регулярное выражение работает в R, но не нашел ничего отличного от других языков для вышеуказанного регулярного выражения. Я могу что-то здесь упустить. Я плохо разбираюсь в R, но насколько я знаю регулярное выражение; Я считаю, что приведенное выше регулярное выражение должно работать так же, как оно работает в java, javascript и python (может быть и в pcre) для всех стандартных механизмов регулярных выражений (насколько мне известно). Мой вопрос: , почему указанное выше регулярное выражение работает по-другому в R?

1 Ответ

4 голосов
/ 26 мая 2020

Похоже, что механизм регулярных выражений TRE (используется по умолчанию в базовых функциях регулярных выражений R), основанный на библиотеке регулярных выражений, изначально написанной Генри Спенсером в 1986 году, соответствует самому короткому совпадению в конце строки, если первый шаблон в регулярном выражении начинается с ленивого квантификатора и заканчивается привязкой $.

Сравните эти случаи :

sub(" +?on.*$", "", Data)  # "Posted by ondrej" "Posted by ona'je"
sub(" +?on.*", "", Data)   # "Posted bydrej on 29 Feb 2020." "Posted bya'je on 29feb 2020"
sub(" +?on(.*)", "", Data) # as expected
sub(" +on.*", "", Data)    # as expected

Что происходит?

  • Первый случай - sub(" +?on.*$", "", Data), а первый шаблон устанавливает жадность всех квантификаторов на одном уровне в регулярном выражении. Таким образом, второй квантификатор, *, будет установлен на ленивый , даже без ? после него, поскольку первое пространство было количественно определено с помощью +?, ленивого квантификатора. Это известная «ошибка» TRE, которая также присутствует в некоторых других движках регулярных выражений, основанных на библиотеке regexl Генри Спенсера.

  • Второй sub(" +?on.*", "", Data) соответствует так же, как если бы он был написан " +?on.*?" (опять же, из-за того, что первый шаблон устанавливает уровень жадности на ленивый на этом уровне) и что будет соответствовать только 1 или более пробелов, а затем on, .*? ничего не соответствует, когда в конце шаблона.

  • Третий, sub(" +?on(.*)", "", Data), дает ожидаемые результаты, потому что второй количественный шаблон, .*, находится на другом уровне (на один уровень глубиной) и его на жадность не влияет +?, находящийся на другом уровне. Итак, (.*) соответствует здесь жадно.

  • Четвертый, sub(" +on.*", "", Data), дает ожидаемые результаты, потому что первый шаблон является жадным, поэтому жадность следующего количественно определенного шаблона также жадна.

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