Як "обернути відповідність" з регулярним виразом?


112

Я використовую RegexBuddy, але я все одно переживаю цю річ: \

Я обробляю файл за рядком. Я побудував "лінійну модель", щоб відповідати тому, що я хочу.

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


EDIT: Я напишу програму, яка використовує цей регулярний вираз, я ще не знаю, чи в python чи php, я роблю цю справу спочатку, щоб дізнатися якийсь регекс :) ​​Є різні типи рядків, я хотів використати регулярний вираз щоб вибрати тип, який мене цікавить. Після того, як я отримав ці рядки, я повинен застосувати інший фільтр просто, щоб не збігатися з відомим значенням, мені потрібні всі інші, не це. (?! Не-розшуку) працює досить чудово, дякую. :-)

Сподіваюсь, це уточнює питання :)


Насправді це здається, що ви можете зробити краще, щоб дати нам трохи більше інформації про те, що ви робите, і побачити, чи хтось може запропонувати альтернативне рішення. Як правило, спроба розбору цілого файлу, побудувавши регулярний вираз, який відповідає кожному рядку, є досить складним маршрутом :)
Dan

Відповіді:


70
(?!Andrea).{6}

Якщо припустимо, що ваш двигун regexp підтримує негативні канали пошуку.

Редагувати: .. або, можливо, ви хочете використовувати [A-Za-z]{6}замість цього.{6}

Редагувати (знову): Зауважте, що шурхіти та огляди, як правило, не є правильним способом "обернути" регулярну відповідність виразів. Regexps насправді не налаштований на негативне узгодження, вони залишають це на будь-якій мові, якою ви їх використовуєте.


Вам потрібно додати ^, який використовує @Vinko Vrsalovic, щоб він не відповідав "ndrea \ n"
bdukes

2
. за замовчуванням не відповідає \ n (деякі мови [напр. Perl] дозволяють увімкнути цю поведінку, але за замовчуванням відповідає всім, АЛЕ \ n).
День

1
(плюс, ОП ніколи не згадував, що струна мала відбуватися на початку рядка)
День

1
що ти означає для ОП?
Андреа Амбу

1
Андреа: ОП означає "оригінальний плакат", тож я мав на увазі вас :)
Dan

47

Для Python / Java,

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

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


4
Це не працює. Ви думаєте про ідіому загартованого жадібного токена. але крапка повинна йти за підказкою, а не раніше. Дивіться це питання . Але такий підхід все одно є надмірним для цього завдання.
Алан Мур

Не знаю, на якій мові написано, але працював як принадність у піднесеному тексті, щоб очистити мої тестові дані. Дякую!
Маттіас Дірікс

1
@AlanMoore Насправді, це майже працює для цього випадку використання. Однак якщо some textзапустити рядок, це поверне неправильний результат.
Zenexer

2
@Zenexer, це я мав на увазі. Якщо крапка знаходиться після пошуку, а не раніше, вона прекрасно працює.
Алан Мур

Ось посилання, що пояснює більше. Я не розумію, чому ?!і не просто !.
Тимо

21

Оновлено відгуками від Алана Мура

У PCRE та подібних варіантах ви можете фактично створити регулярний вираз, який відповідає будь-якій лінії, що не містить значення:

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

Це називається загартованою жадібною ознакою . Мінус у тому, що він працює не так добре.


1
Це загартований жадібний жетон в довгому вигляді. Просто помістіть точку (або [\s\S], що корисно тільки в JavaScript) після другого випереджаючого перегляду, і вам не потрібно перший: ^(?:(?!Andrea).)*$.
Алан Мур

@AlanMoore Приємно! Я не зміг знайти жодного встановленого шаблону, який би працював так, тому я придумав свою власну. Замість того, щоб я брав вашу відповідь, ви повинні надати це як своє.
Zenexer

Це добре, відповідей вже багато. І ви заслуговуєте на заслугу за те, що винайшли ідіому самостійно. Ура!
Алан Мур

Чому ви пропонуєте використовувати [\S\s]? ОП говорить про відповідні рядки, не містять слова "Андреа". Не про перевірку, чи весь рядок містить це слово. Я щось пропускаю?
x-yuri

@ x-yuri Я думаю, ти маєш рацію. Напевно, я відповів на запитання, яке я вперше відвідав цю сторінку, ігноруючи розбіжність. Мій зв’язок недостатньо хороший, щоб зараз оновити відповідь (<10 кбіт / с)
Zenexer

11

Якою мовою ви користуєтесь? Для цього важливі можливості та синтаксис реалізації системи регулярних виразів.

Ви можете використовувати погляд вперед. Використання python як приклад

import re

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

Щоб розбити це:

(?! Андреа) означає "збіг, якщо наступні 6 символів не є" Андреа ""; якщо так

\ ш означає "символ слова" - буквено-цифрові символи. Це еквівалентно класу [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

У перлі можна зробити

обробити ($ line) if ($ line = ~! / Andrea /);


4
Цей синтаксис неправильний. Я думаю, ви маєте на увазі процес ($ line), якщо $ line! ~ / Андреа /
dland
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.