Regex - как сопоставить все, кроме определенного шаблона
171
Как мне написать регулярное выражение для соответствия любой строке, которая не соответствует определенному шаблону? Я столкнулся с ситуацией, когда я должен соответствовать шаблону (A и ~ B).
Но если у вас нет реализации регулярного выражения с этой функцией (см. Сравнение разновидностей регулярных выражений ), вам, вероятно, придется создавать регулярное выражение с основными функциями самостоятельно.
Совместимое регулярное выражение только с базовым синтаксисом будет:
[0-8]\d\d|\d[0-8]\d|\d\d[0-8]
Это также соответствует любой последовательности из трех цифр, которой нет 999.
Предварительный просмотр - это не стандартный синтаксис регулярных выражений, это расширение Perl, оно будет работать только в Perl, PCRE (Perl-совместимом RegEx) или других нестандартных реализациях
Juliano
10
Это может быть не стандартно, но разве большинство современных языков не поддерживают это? Какой язык не поддерживает прогнозирование в эти дни?
я думаю, что последнее регулярное выражение также не будет соответствовать 009, 019 ... и т. д.
Себастьян Viereck
1
Стандартный Lex для C не использует PCRE :-(
pieman72
30
Если вы хотите сопоставить слово A в строке, а не слово B. Например: если у вас есть текст:
1. I have a two pets - dog and a cat
2. I have a pet - dog
Если вы хотите найти строки текста, в которых есть собака для домашнего питомца и у которых нет кошки, вы можете использовать это регулярное выражение:
Он не упомянул об этом в вопросе, но ОП фактически использует команду DOS findstr. Он предоставляет лишь небольшую часть возможностей, которые вы ожидаете найти в инструменте регулярных выражений; Lookahead не среди них. (Я просто добавил тег findstr сам.)
Алан Мур
2
хм, да я сейчас нашел в одном из своих комментариев к постам. Я видел Regex в названии. В любом случае, если кто-то найдет этот пост при поиске того же самого для регулярного выражения, как я, возможно, это могло бы быть полезным для кого-то :) спасибо за комментарии
Aleks
15
Сопоставьте с шаблоном и используйте основной язык для инвертирования логического результата совпадения. Это будет намного более разборчивым и ремонтопригодным.
Тогда я просто получаю (~ A или B) вместо (A и ~ B). Это не решает мою проблему.
не
1
Псевдокод: String toTest; if (toTest.matches (A) AND! toTest.matches (B)) {...}
Бен С
Я должен был быть более ясным - части не полностью независимы. Если A соответствует части строки, мы заботимся, соответствует ли ~ B остальной части (но не обязательно всему). Это было для функции командной строки Windows findstr, которая, как я обнаружил, ограничена истинными регулярными выражениями, так что спорный вопрос.
не
8
нет, воскресение этого древнего вопроса, потому что у него было простое решение, которое не было упомянуто. (Нашел свой вопрос во время исследования квеста «Регулярное вознаграждение» .)
Я столкнулся с ситуацией, когда я должен соответствовать шаблону (A и ~ B).
Основное выражение для этого пугающе просто: B|(A)
Вы просто игнорируете общие совпадения и изучаете захваты группы 1, которые будут содержать A.
Пример (со всеми заявлениями об отказе от синтаксического анализа html в регулярных выражениях): A это цифры, B это цифры внутри <a tag
Регулярное выражение: <a.*?<\/a>|(\d+)
Демо (посмотрите на Группу 1 в нижней правой панели)
Это звучит слишком хорошо, чтобы быть правдой! К сожалению, это решение не универсально, и оно терпит неудачу в Emacs, даже после замены \dна [[:digit:]]. В первой ссылке упоминается, что она специфична для Perl и PHP: «Существует вариант с использованием синтаксиса, специфичного для Perl и PHP, который выполняет то же самое».
Мигельморин
4
Дополнение к обычному языку также является обычным языком, но для его построения необходимо создать DFA для обычного языка и внести любое допустимое изменение состояния в ошибку. Смотрите это для примера. То, что страница не говорит, - то, что это преобразовало /(ac|bd)/в /(a[^c]?|b[^d]?|[^ab])/. Преобразование из DFA обратно в регулярное выражение не является тривиальным. Это проще, если вы можете использовать регулярное выражение без изменений и изменить семантику в коде, как предложено ранее.
Если бы я имел дело с реальными регулярными выражениями, то все это было бы спорным. Теперь кажется, что регулярное выражение ссылается на туманное пространство соответствия шаблонов (CSG), которое поддерживает большинство языков. Так как мне нужно сопоставить (A и ~ B), нет способа удалить отрицание и все же сделать все за один шаг.
не
Lookahead, как описано выше, сделал бы это, если бы findstr сделал что-то кроме настоящих регулярных выражений DFA. Все это немного странно, и я не знаю, почему я должен делать этот стиль командной строки (сейчас). Это просто еще один пример того, как мои руки связаны.
не
1
@ notnot: Вы используете findstr из Windows? Тогда вам просто нужно / V. Как: findstr Входной файл | findstr / v B> outputfile.txt Первая соответствует всем строкам с A, вторая соответствует всем строкам без B.
Juliano
Спасибо! Это на самом деле именно то, что мне было нужно. Я не задавал вопрос таким образом, поэтому я все же отвечал Гамбо на более обобщенный ответ.
Вы, вероятно, хотите упомянуть, что вам нужно присоединиться снова.
Томдемайт
Аналогичный подход используется replacestr.replace(/re/g, ''), тогда нет необходимости возвращаться к ним. также, если вы добавите хороший трейлинг? как str.replace(/\re\s?/g, '')тогда, вы избавляетесь от любых дубликатов, которые вы могли бы получить от чего-то, заменяемого в середине строки
Группа $2была сделана без захвата там, что вы бы избежать.
Пример:
Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");
Первая группа захвата определяет шаблон, который вы хотите избежать. Последняя группа захвата захватывает все остальное. Просто зачитайте эту группу $2.
findstr
тег, так как все ответы здесь недействительны для тега.Ответы:
Вы можете использовать прогнозное утверждение:
Этот пример соответствует трем цифрам, кроме
999
.Но если у вас нет реализации регулярного выражения с этой функцией (см. Сравнение разновидностей регулярных выражений ), вам, вероятно, придется создавать регулярное выражение с основными функциями самостоятельно.
Совместимое регулярное выражение только с базовым синтаксисом будет:
Это также соответствует любой последовательности из трех цифр, которой нет
999
.источник
Если вы хотите сопоставить слово A в строке, а не слово B. Например: если у вас есть текст:
Если вы хотите найти строки текста, в которых есть собака для домашнего питомца и у которых нет кошки, вы можете использовать это регулярное выражение:
Он найдет только вторую строку:
источник
findstr
. Он предоставляет лишь небольшую часть возможностей, которые вы ожидаете найти в инструменте регулярных выражений; Lookahead не среди них. (Я просто добавил тег findstr сам.)Сопоставьте с шаблоном и используйте основной язык для инвертирования логического результата совпадения. Это будет намного более разборчивым и ремонтопригодным.
источник
нет, воскресение этого древнего вопроса, потому что у него было простое решение, которое не было упомянуто. (Нашел свой вопрос во время исследования квеста «Регулярное вознаграждение» .)
Основное выражение для этого пугающе просто:
B|(A)
Вы просто игнорируете общие совпадения и изучаете захваты группы 1, которые будут содержать A.
Пример (со всеми заявлениями об отказе от синтаксического анализа html в регулярных выражениях): A это цифры, B это цифры внутри
<a tag
Регулярное выражение:
<a.*?<\/a>|(\d+)
Демо (посмотрите на Группу 1 в нижней правой панели)
Ссылка
Как сопоставить шаблон кроме ситуаций s1, s2, s3
Как соответствовать шаблону, если ...
источник
\d
на[[:digit:]]
. В первой ссылке упоминается, что она специфична для Perl и PHP: «Существует вариант с использованием синтаксиса, специфичного для Perl и PHP, который выполняет то же самое».Дополнение к обычному языку также является обычным языком, но для его построения необходимо создать DFA для обычного языка и внести любое допустимое изменение состояния в ошибку. Смотрите это для примера. То, что страница не говорит, - то, что это преобразовало
/(ac|bd)/
в/(a[^c]?|b[^d]?|[^ab])/
. Преобразование из DFA обратно в регулярное выражение не является тривиальным. Это проще, если вы можете использовать регулярное выражение без изменений и изменить семантику в коде, как предложено ранее.источник
шаблон - ре
вернет все, кроме шаблона.
Тест здесь
источник
replace
str.replace(/re/g, '')
, тогда нет необходимости возвращаться к ним. также, если вы добавите хороший трейлинг? какstr.replace(/\re\s?/g, '')
тогда, вы избавляетесь от любых дубликатов, которые вы могли бы получить от чего-то, заменяемого в середине строкиМой ответ здесь также может решить вашу проблему:
https://stackoverflow.com/a/27967674/543814
$1
вы читаете группу$2
.$2
была сделана без захвата там, что вы бы избежать.Пример:
Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");
Первая группа захвата определяет шаблон, который вы хотите избежать. Последняя группа захвата захватывает все остальное. Просто зачитайте эту группу
$2
.источник
тогда используйте то, что захватывает группа 2 ...
источник