Режекс рівно n АБО м разів


105

Розглянемо наступний регулярний вираз, де Xє будь-який регулярний вираз.

X{n}|X{m}

Це регулярний вираз буде перевірити Xвідбуваються точно n або mраз.

Чи існує кількісний показник регулярних виразів, який може перевірити на наявність події Xрівно nчи mраз?


Ні . Два входжень Xце краще , що ви можете отримати для загального m, n.
Джон Дворак

Якби це була моя проблема, я б спробував зворотні регерекси і почав би з (X)\1{n-1}(?:\1{m-n-1}). Я знаю, що це збіги Xхоча б один раз, але для початку спробуйте цю просту річ, а потім удосконаліть, використовуючи замість них штрихові головки або диски (X).
nalply

Відповіді:


91

Не існує єдиного кількісного показника, який означає "рівно m або n разів". Те, як ви це робите, добре.

Альтернатива:

X{m}(X{k})?

де m < nі kє значення n-m.


67

Ось повний перелік кванторів (посилання http://www.regular-expressions.info/reference.html ):

  • ?, ??- 0 або 1 випадків ( ??лінивий, ?жадібний)
  • *, *?- будь-яка кількість випадків
  • +, +?- принаймні одна поява
  • {n}- саме nвипадки
  • {n,m}- nдо mвипадків, включно
  • {n,m}?- nдо mвипадків, ледачих
  • {n,}, {n,}?- принаймні nвиникнення

Щоб отримати "рівно N або M", вам потрібно двічі написати кількісну оцінку, якщо тільки m, n не є спеціальними:

  • X{n,m} якщо m = n+1
  • (?:X{n}){1,2} якщо m = 2n
  • ...

1
Чому це ?:потрібно в m = 2nприкладі if ? Здається, це добре працює без мене.
erb

7
@erb, якщо ви не залишитесь ?:, група стає захоплюючою групою. Окрім того, що запам'ятовує механізм регулярного генерування, він не повинен, якщо ви захоплюєте групи після цього, їхні ідентифікатори змінюватимуться. Якщо ви використовуєте ваш регекс для заміни, вам доведеться відрегулювати заміну.
Джон Дворак


3

TLDR; (?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

Схоже, ви хочете "xn разів" або "xm разів", я думаю, що дослівний переклад на регулярний вираз був би (x{n}|x{m}). таким: https://regex101.com/r/vH7yL5/1

або, у випадку, коли у вас може бути послідовність більше m "x" s (припустимо, що m> n), ви можете додати "follow no" x "'і" після чого не "x", перекладаючи на, [^x](x{n}|x{m})[^x]але це буде припустимо, що позаду і за вами "x" s завжди є персонаж. Як ви можете побачити тут: https://regex101.com/r/bB2vH2/1

ви можете змінити його на (?:[^x]|^)(x{n}|x{m})(?:[^x]|$), перекладаючи на "слідом за" x "або наступним початком рядка" та "після цього немає" x "або після закінчення рядка". Але все-таки вона не збігатиметься з двома послідовностями з лише одним символом між ними (тому що перший матч потребує символу після, а другий - раніше), як ви можете бачити тут: https://regex101.com/r/ oC5oJ4 / 1

Нарешті, щоб відповідати віддаленому матчу з одним символом, ви можете додати позитивний погляд вперед (? =) На "ні" х "після" або позитивний погляд позаду (? <=) На "ні" х "раніше", ось так: https://regex101.com/r/mC4uX3/1

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

Таким чином ви будете відповідати лише точній кількості "х", яку ви хочете.


1

Дивлячись на відповідь Енгардена, вони констатують, що їх передостаннє вираження не збігатиметься з послідовностями лише одного символу між ними. Існує простий спосіб виправити це, не використовуючи погляд вперед / погляд назад, і це замінити початковий / кінцевий символ на граничний символ. Це дозволяє вам відповідати меж слова, що включає початок / кінець. Таким чином, відповідним виразом має бути:

(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)

Як ви можете побачити тут: https://regex101.com/r/oC5oJ4/2 .


1
Класно, я не був знайомий з тим, як регекс обробляє межі. Єдине питання цього методу, коли ви використовуєте нестандартну межу. Сказати погляд: regex101.com/r/j0nkeo/1 та regex101.com/r/4Ix7Dr/1
Укріплений

1
@Enhardened - це хороший момент, здається, проблема з кількома групами відповідності, які перетинаються. Це ситуація, коли вам потрібно використовувати огляд.
rozza2058

1

Дуже стара публікація, але я хотів би внести щось, що могло б допомогти. Я спробував це саме так, як зазначено в запитанні, і він працює, але є привід: Порядок кількості має значення. Врахуйте це:

#[a-f0-9]{6}|#[a-f0-9]{3}

Тут ви знайдете всі випадки шістнадцяткових кольорових кодів (вони три або 6 цифр). Але коли я перевертаю це так

#[a-f0-9]{3}|#[a-f0-9]{6}

він знайде лише трицифрові або перші 3 цифри шестизначних. Це має сенс, і Regex pro може помітити це відразу, але для багатьох це може бути своєрідною поведінкою. Є кілька вдосконалених функцій Regex, які можуть уникнути цієї пастки незалежно від порядку, але далеко не всі опиняються по колу до моделей Regex.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.