Regex: Согласование путем исключения, без надежды – возможно ли это?
В некоторых вариантах регулярных выражений [отрицательные] утверждения нулевой ширины (look-ahead / look-behind) не поддерживаются.
Это делает чрезвычайно трудным (невозможным?) Утверждать исключение. Например, «каждая строка, которая не имеет« foo »на ней», вот так:
^((?!foo).)*$
Можно ли добиться такого же результата без использования внешнего вида (сложность и производительность на данный момент отложены)?
- Исключить символы из classа символов
- Заменить первое вхождение строки в Python
- Регулярное выражение для буквенно-цифровых и подчеркиваний
- Регулярное выражение для принудительного применения сложных паролей, соответствующих 3 из 4 правил
- Несколько слов в любом порядке с использованием регулярного выражения
- Какие специальные символы должны быть экранированы в регулярных выражениях?
- RegEx, чтобы убедиться, что строка содержит по крайней мере один символ нижнего регистра, символ верхнего регистра, цифру и символ
- Regex: соответствие до первого появления символа
- Сделать регистр с регулярным выражением нечувствительным в ASP.NET RegularExpressionValidator
- Regex найти повторяющиеся числа
- RegEx для исключения конкретной строковой константы
- Регулярное выражение противоположно
- Проверка правильности электронной почты Regex
ОБНОВЛЕНИЕ: он не работает «с двумя ff до оо», как отметил @Ciantic в комментариях.
^(f(o[^o]|[^o])|[^f])*$
ПРИМЕЧАНИЕ. Гораздо проще просто отменить совпадение на стороне клиента, а не использовать указанное выше регулярное выражение.
Регулярное выражение предполагает, что каждая строка заканчивается символом новой строки, если она не видна в регулярных выражениях C ++ и grep.
Примеры программ в Perl, Python, C ++ и grep
дают одинаковый результат.
-
Perl
#!/usr/bin/perl -wn print if /^(f(o[^o]|[^o])|[^f])*$/;
-
питон
#!/usr/bin/env python import fileinput, re, sys from itertools import ifilter re_not_foo = re.compile(r"^(f(o[^o]|[^o])|[^f])*$") for line in ifilter(re_not_foo.match, fileinput.input()): sys.stdout.write(line)
-
C ++
#include
#include #include int main() { boost::regex re("^(f(o([^o]|$)|([^o]|$))|[^f])*$"); //NOTE: "|$"s are there due to `getline()` strips newline char std::string line; while (std::getline(std::cin, line)) if (boost::regex_match(line, re)) std::cout << line << std::endl; } -
Grep
$ grep "^\(f\(o\([^o]\|$\)\|\([^o]\|$\)\)\|[^f]\)*$" in.txt
Пример файла:
foo 'foo' abdfoode abdfode abdfde abcde f fo foo fooo ofooa ofo ofoo
Вывод:
abdfode abdfde abcde f fo ofo
Перешел через этот вопрос и принял тот факт, что не было полностью работающего регулярного выражения как личный вызов. Я считаю, что мне удалось создать регулярное выражение, которое работает для всех входных данных – при условии, что вы можете использовать атомарные группировки / обладающие квантификаторами .
Конечно, я не уверен, есть ли какие-либо вкусы, которые позволяют группировать атомы, но не искать, но вопрос спросил, возможно ли в регулярном выражении исключить исключение без искажений, и это технически возможно:
\A(?:$|[^f]++|f++(?:[^o]|$)|(?:f++o)*+(?:[^o]|$))*\Z
Объяснение:
\A #Start of string (?: #Non-capturing group $ #Consume end-of-line. We're not in foo-mode. |[^f]++ #Consume every non-'f'. We're not in foo-mode. |f++(?:[^o]|$) #Enter foo-mode with an 'f'. Consume all 'f's, but only exit foo-mode if 'o' is not the next character. Thus, 'f' is valid but 'fo' is invalid. |(?:f++o)*+(?:[^o]|$) #Enter foo-mode with an 'f'. Consume all 'f's, followed by a single 'o'. Repeat, since '(f+o)*' by itself cannot contain 'foo'. Only exit foo-mode if 'o' is not the next character following (f+o). Thus, 'fo' is valid but 'foo' is invalid. )* #Repeat the non-capturing group \Z #End of string. Note that this regex only works in flavours that can match $\Z
Если по какой-либо причине вы можете использовать атомарную группировку, но не обладающие квантификаторами и не искать, вы можете использовать:
\A(?:$|(?>[^f]+)|(?>f+)(?:[^o]|$)|(?>(?:(?>f+)o)*)(?:[^o]|$))*\Z
Как отмечают другие, хотя, вероятно, более практично просто отрицать матч другими способами.
Обычно вы можете искать foo и инвертировать результат соответствия регулярного выражения из кода клиента.
Для простого примера предположим, что вы хотите проверить, что строка содержит только определенные символы.
Вы могли бы написать следующее:
^[A-Za-z0-9.$-]*$
и принять true
результат как действительный, или вот так:
[^A-Za-z0-9.$-]
и принять false
результат как действительный.
Конечно, это не всегда вариант: иногда вам просто нужно поместить выражение в файл конфигурации или передать его в другую программу, например. Но стоит вспомнить. Ваша конкретная проблема, например, выражение намного проще, если вы можете использовать это отрицание.
Я наткнулся на этот вопрос, ища свое решение для исключения регулярных выражений, где я пытаюсь исключить последовательность внутри своего регулярного выражения.
Моя первоначальная реакция на эту ситуацию: например, «каждая строка, которая не имеет« foo »на ней», просто заключалась в использовании опции -v для инвертирования соответствия в grep.
grep -v foo
это возвращает все строки в файле, который не соответствует ‘foo’
Это так просто, у меня сильное чувство, что я просто неправильно понял ваш вопрос ….