Regex до, але не включаючи


81

Що стосується регулярного виразу, яким є синтаксис пошуку до, але не включаючи? Подібно:

Haystack:
The quick red fox jumped over the lazy brown dog

Expression:
.*?quick -> and then everything until it hits the letter "z" but do not include z

Відповіді:


161

Явний спосіб сказати "шукати до, Xале не включаючи X":

(?:(?!X).)*

де X може бути будь-який регулярний вираз.

Однак у вашому випадку це може бути надмірним - тут це буде найпростіший спосіб

[^z]*

Це збігається з будь-чим, крім zі тому зупиняється безпосередньо перед наступним z.

Так .*?quick[^z]*буде відповідати The quick fox jumps over the la.

Однак, як тільки у вас є кілька простих листів, на які слід звернути увагу, наприклад, (?:(?!X).)*у справу вступає

(?:(?!lazy).)*- збігати що-небудь до початку слова lazy.

Це використовує твердження lookahead , точніше негативний lookahead.

.*?quick(?:(?!lazy).)*буде відповідати The quick fox jumps over the.

Пояснення:

(?:        # Match the following but do not capture it:
 (?!lazy)  # (first assert that it's not possible to match "lazy" here
 .         # then match any character
)*         # end of group, zero or more repetitions.

Крім того, під час пошуку ключових слів, можливо, ви захочете оточити їх якорями меж слова: \bfox\bбуде відповідати лише повному слову, foxале не лисиці foxy.

Примітка

Якщо текст, якому потрібно зіставити, також може містити розриви рядків, вам потрібно буде встановити параметр "крапка відповідає всім" вашого механізму регулярних виразів. Зазвичай ви можете досягти цього, додавши (?s)до регулярного виразу, але це не працює у всіх механізмах регулярних виразів (зокрема JavaScript).

Альтернативне рішення:

У багатьох випадках ви також можете використовувати більш просте, читабельне рішення, яке використовує ледачий квантор. Додаючи a ?до *квантора, він намагатиметься зіставити якомога менше символів із поточної позиції:

.*?(?=(?:X)|$)

буде відповідати будь-якій кількості символів, зупиняючись прямо перед X(що може бути будь-яким регулярним виразом) або кінцем рядка (якщо Xне збігається). Вам також може знадобитися встановити параметр "крапка відповідає всім", щоб це працювало. (Примітка: я додав групу, яка не фіксує X, щоб надійно ізолювати її від чергування)


+1 Дійсно приємна відповідь, на жаль, не працює grep, але ця відповідь працює.
Alexandre Lavoie

@AlexandreLavoie: Цікаво. Чому повинен працювати інший, а не цей? Обидва використовують твердження про пошук. Можливо, це просто через (?:...)групу, яка не захоплює? Це працює з ((?!X).)*?
Тім Пітцкер,

1
Насправді не знаю, я не експерт з регулярних виразів і не grep. Я використовував grepдля фільтрації запитів лише на одну базу даних із mysql bin transformet у sql. Ось звір:grep -Po "(?s)use database_to_keep(.*?)(?=^use)" mysql-bin.000045.sql > filtered.sql
Alexandre Lavoie

Схоже на конфлікт з bash, оскільки коли я натискаю Upклавішу, остання команда не та, яку я використовував:grep -Po "(?s)use database_to_keep(.*?)(?:(?!^use).)*" mysql-bin.000045.sql > filtered.sql
Alexandre Lavoie

1
Гарне редагування, @Tim, просто додай $альтернативу: заміни .*?(?=X)на.*?(?=X|$)
Wiktor Stribiżew

15

Синтаксис випередження регулярного виразу може допомогти вам досягти вашої мети. Таким чином, регулярний вираз для вашого прикладу є

.*?quick.*?(?=z)

І важливо помітити .*?ліниве співпадіння перед (?=z)пошуком: вираз відповідає підрядку до першого входження zбукви.

Ось зразок коду C #:

const string text = "The quick red fox jumped over the lazy brown dogz";

string lazy = new Regex(".*?quick.*?(?=z)").Match(text).Value;
Console.WriteLine(lazy); // The quick red fox jumped over the la

string greedy = new Regex(".*?quick.*(?=z)").Match(text).Value;
Console.WriteLine(greedy); // The quick red fox jumped over the lazy brown dog

0

Спробуйте це

(.*?quick.*?)z

3
Сюди входить "z" у матчі, а саме цього і вимагає уникнути особа, що ставиться. Можливо, регулярний вираз має бути терміном у | | alternative, і цей альтернативний регулярний вираз використовується для виконання декількох збігів. Якщо "z" - це початок рядка, який би відповідав іншому терміну в альтернативному варіанті, тоді це збіг буде втрачено, оскільки "z" вже споживається поточним збігом.
Щепан Голишевський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.