Как «обратное совпадение» с регулярным выражением?

112

Я использую RegexBuddy, но у меня все равно проблемы с этим: \

Я обрабатываю файл построчно. Я построил «линейную модель», чтобы соответствовать тому, что я хочу.

Теперь я хотел бы выполнить обратное сопоставление ... т.е. я хочу сопоставить строки, в которых есть строка из 6 букв, но только если эти шесть букв не являются Андреа , как мне это сделать?


РЕДАКТИРОВАТЬ: Я напишу программу, которая использует это регулярное выражение, я еще не знаю, в python или php я делаю это сначала, чтобы выучить какое-то регулярное выражение :) Существуют разные типы строк, я хотел использовать регулярное выражение чтобы выбрать тип, который меня интересует. Получив эти строки, я должен применить другой фильтр, просто чтобы не совпадать с известным значением, мне нужны все остальные, а не это. (?! Не разыскивается) работает нормально, спасибо. :-)

Надеюсь, это проясняет вопрос :)

Андреа Амбу
источник
На самом деле похоже, что вам может быть лучше предоставить нам немного больше информации о том, что вы делаете, и посмотреть, может ли кто-нибудь предложить альтернативное решение. Как правило, попытка проанализировать весь файл путем построения регулярного выражения, которое соответствует каждой строке, является довольно сложным путем :)
Дэн,

Ответы:

70
(?!Andrea).{6}

Предполагая, что ваш механизм регулярных выражений поддерживает отрицательный просмотр вперед.

Изменить: ..или, возможно, вы бы предпочли использовать [A-Za-z]{6}вместо.{6}

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

Дэн
источник
Вам нужно добавить ^, который использует @Vinko Vrsalovic, чтобы он не совпадал с "ndrea \ n"
bdukes
2
. не соответствует \ n по умолчанию (некоторые языки [например, Perl] позволяют вам включить это поведение, но по умолчанию. соответствует всему, НО \ n).
Дэн
1
(плюс, OP никогда не упоминал, что строка должна располагаться в начале строки)
Дэн
1
что ты имеешь в виду под ОП?
Андреа Амбу
1
Андреа: OP означает «оригинальный плакат», так что я имел в виду вас :)
Дэн
47

Для Python / Java,

^(.(?!(some text)))*$

http://www.lisnichenko.com/articles/javapython-inverse-regex.html

Дмитро
источник
4
Это не работает. Вы думаете об идиоме Tempered Greedy Token. но точка должна идти после опережающего просмотра, а не до него. См. Этот вопрос . Но такой подход в любом случае является излишним для этой задачи.
Алан Мур
Не знаю, на каком языке он написан, но сработал как шарм в Sublime text, чтобы очистить мои тестовые данные. Спасибо!
Matthias dirickx
1
@AlanMoore На самом деле, для этого варианта использования это почти сработает. Однако если some textзапустить строку, она вернет неверный результат.
Zenexer
2
@Zenexer, я это имел в виду. Если точка стоит после опережающего просмотра, а не до, он работает отлично.
Алан Мур,
Вот ссылка, которая объясняет больше. Не понимаю почему ?!и не просто так !.
Timo
21

Обновлено с учетом отзывов Алана Мура

В PCRE и аналогичных вариантах вы можете создать регулярное выражение, которое соответствует любой строке, не содержащей значения:

^(?:(?!Andrea).)*$

Это называется закаленным жадным токеном . Обратной стороной является то, что он не работает хорошо.

Zenexer
источник
1
Это закаленный жадный жетон в полной форме. Просто поместите точку (или [\s\S], что полезно только в JavaScript) после второго опережающего просмотра, и вам не нужно первый: ^(?:(?!Andrea).)*$.
Алан Мур,
@AlanMoore Отлично! Я не смог найти какой-либо установленный шаблон, который работал бы таким образом, поэтому я придумал свой собственный. Вместо того, чтобы я принимал ваш ответ, вы должны представить его как свой собственный.
Zenexer
Ничего страшного, хороших ответов уже предостаточно. И вы заслуживаете похвалы за то, что изобрели эту идиому самостоятельно. Ура!
Алан Мур,
Почему вы предлагаете использовать [\S\s]? OP говорит о совпадающих строках, не содержащих слова "Andrea". Не о проверке, есть ли это слово во всей строке. Я что-то упускаю?
x-
@ x-yuri Думаю, ты прав. Я, вероятно, ответил на вопрос, который у меня был, - я впервые посетил эту страницу, игнорируя несоответствие. Мое соединение недостаточно хорошее, чтобы обновить ответ прямо сейчас (<10 кбит / с)
Zenexer
11

На каком языке ты говоришь? Для этого важны возможности и синтаксис реализации регулярного выражения.

Вы можете использовать прогноз. Использование Python в качестве примера

import re

not_andrea = re.compile('(?!Andrea)\w{6}', re.IGNORECASE)

Чтобы разбить это:

(?! Андреа) означает «совпадение, если следующие 6 символов не являются« Андреа »»; если так то

\ w означает «словесный символ» - буквенно-цифровые символы. Это эквивалент класса [a-zA-Z0-9_]

\ w {6} означает ровно 6 символов слова.

re.IGNORECASE означает, что вы исключите "Andrea", "andrea", "ANDREA" ...

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

Хэмиш Даунер
источник
7

Утверждение отрицательного просмотра вперед

(?!Andrea)

Это не совсем перевернутое совпадение, но это лучшее, что вы можете сделать напрямую с регулярным выражением. Однако не все платформы их поддерживают.

Винко Врсалович
источник
1
Я не вижу, чтобы матч начинался с начала очереди, пока спрашивающий не уточнит. Так почему ^?
Хэмиш Даунер,
Поскольку я понял, что он хотел проверить в начале строки, отредактировал данные пояснения
Винко Врсалович
5

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

На панели инструментов на панели «Тест» установите для области тестирования значение «Построчно». Когда вы это сделаете, под кнопкой «Список всех» на той же панели инструментов появится элемент «Список всех строк без совпадений». (Если вы не видите кнопку «Список всех», нажмите кнопку «Сопоставить» на главной панели инструментов.)

На панели GREP вы можете включить флажки «на основе строк» ​​и «инвертировать результаты», чтобы получить список несовпадающих строк в файлах, которые вы просматриваете.

Ян Гойвертс
источник
5

(?!полезно на практике. Хотя, строго говоря, прогнозирование вперед не является регулярным выражением в математическом смысле.

Вы можете написать обратное регулярное выражение вручную.

Вот программа для автоматического расчета результата. Его результат генерируется машиной, что обычно намного сложнее, чем рукописное. Но результат работает.

слабый
источник
1

Я только что придумал этот метод, который может потребовать много оборудования, но он работает:

Вы можете заменить все символы, которые соответствуют регулярному выражению, пустой строкой.

Это один лайнер:

notMatched = re.sub(regex, "", string)

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

Это вернет вам только строковый результат, а не любые объекты соответствия!

Маттиас Херрманн
источник
-3

В Perl вы можете сделать

process ($ line) if ($ line = ~! / Andrea /);

фрикр
источник
4
Этот синтаксис неверен. Я думаю, вы имеете в виду процесс ($ line), если $ line! ~ / Andrea /
dland