Регулярное выражение для "максимум" - PullRequest
0 голосов
/ 06 марта 2020

Я сейчас думаю о том, как лучше express «Максимум два» как регулярное выражение.

str_detect("xxx", "x{0,2}") дает TRUE и я понимаю почему. Например из-за первых двух x. Я хочу регулярное выражение, которое дает FALSE. str_detect("xxx", "x{0,2}[^x]") достигает этого, это нормально. str_detect("xxx", "x{0,2}(?!x)") приводит к TRUE, я очень удивлен из-за этого. Почему это так?

Можете ли вы вспомнить другие регулярные выражения, которые умнее x{0,2}[^x]? Я думаю, что все в порядке, но мне интересно, если нет более короткого решения.

1 Ответ

2 голосов
/ 06 марта 2020

Вы должны уточнить значение «максимум». Вы используете выражение для обозначения 0, 1 или 2 вхождений, и оно представлено с помощью {0,2} ограничивающего квантификатора .

Однако одно повторение символа может произойти сразу или на некотором расстоянии между ними. То есть повторений могут быть последовательными и непоследовательными . В первых случаях мы используем x{0,2} в положительном контексте или x{3} в отрицательном, во втором - количественные классы отрицательных символов, которые исключают символ, например (?:[^x]*x){0,2} (положительный контекст) / (?:[^x]*x){3} (негативный контекст).

Что с положительным / отрицательным контекстом? Когда вы говорите «не более 2», оно равно «не более 3». Таким образом, если есть N + 1 совпадений, совпадение должно завершиться неудачей. Положительные контексты устанавливаются с регулярными контекстами потребления в большинстве случаев, отрицательные контексты обычно устанавливаются в отрицательных значениях.

Примеры "Максимум" :

  • Максимум 2 вхождения последовательных b символов в строке: str_detect(c("aaa","abc","abb","bbb","babnbdb"), "^(?!.*b{3})") (=> [1] TRUE TRUE TRUE FALSE TRUE)
  • Не более 2 последовательных повторений b в слово: str_extract_all("aaa abc abb bbb babnbdb", "\\b(?!\\p{L}*b{3})\\p{L}+\\b") (=> [1] "aaa" "abc" "abb" "babnbdb")
  • Не более 2 непоследовательных повторений b в строке: str_detect(c("aaa","abc","abb","bbb","babnbdb"), "^(?:[^b]*b){0,2}[^b]*$") (=> [1] TRUE TRUE TRUE FALSE FALSE)
  • Не более 2 непоследовательных повторений буквы b в любом слове: str_extract_all("aaa abc abb bbb babnbdb", "\\b(?!(?:[\\p{L}--[b]]*b){3})\\p{L}+\\b") (=> [1] "aaa" "abc" "abb")

См. R демо онлайн

...