Как превратить любое регулярное выражение в дополнение к себе без сложного редактирования вручную?
Ниже приведены псевдо-примеры, а не реальное регулярное выражение, но все же пример того, что я имею в виду:
.* (anything)
-.* (NOT anything)
[A-Z] (Any letter A to Z, caps only)
-[A-Z] (NOT any letter A to Z, caps only)
EDIT: Изменено в дополнение к дополнению. Здесь, где было сделано изменение: "превратите любое регулярное выражение в дополнение самого себя"
Ответы
Ответ 1
Прежде всего, я считаю, что вы имеете в виду дополнение регулярного выражения, а не инверсное. Обратное к регулярному выражению не имеет большого смысла; но если рассматривать как функцию, я полагаю, вы могли бы сказать, что обратный к собору является генератором, который генерирует все соответствующие строки - или что-то. С другой стороны, дополнение языка - это все те строки, которые не находятся на исходном языке.
Затем здесь нужно рассмотреть два вида:
Фундаментально
Дополнение регулярного языка является регулярным. Это означает, что можно создать принимающий DFA для дополнения (и сделать это очень просто, на самом деле: просто поменять не принимающее состояние с набором принимающих состояний). Любой такой DFA может быть выражен как регулярное выражение - так что в принципе вы действительно можете сделать такое регулярное выражение.
В качестве отправной точки см. статью wikipedia на Regular Languages .
Практически
Типичный синтаксис regex, совместимый с perl, используемый в большинстве современных языков в настоящее время, не имеет оператора комплементации. Для полного регулярного выражения вы можете получить что-то подобное, используя отрицательный оператор lookahead: (?!X)
будет соответствовать строке точно, когда X
не будет. Однако это плохая замена оператора дополнения, поскольку вы не сможете использовать его как часть большого регулярного выражения обычным способом; это регулярное выражение не "потребляет" вход, что означает, что он ведет себя по-разному в сочетании с другими операторами.
Например, если вы сопоставляете числовые строки как [0-9]*
, чтобы соответствовать всей строке, которую вы добавили бы ^
и добавили $
, но чтобы использовать эту технику для поиска дополнения, которое вам нужно написать ^(?!^[0-9]*$).*$
- и обычная конкатенация такого отрицательного регулярного выражения, насколько я могу судить, отменена.
Несколько по иронии судьбы, практическое воплощение регулярных выражений теоретически более мощное из-за обратных ссылок, но практически менее гибкое, поскольку язык не может легко выразить операции комплемента и пересечения.
Ответ 2
Просто запустите регулярное выражение и логически инвертируйте вывод. Итак, измените:
if(/foo/)
в
if(!/foo/)
Символьные классы могут быть инвертированы с помощью ведущего карат:
[A-Z] → [^ A-Z]
У многих специальных символов также есть инверсии, если вы воспользуетесь спецификатором.
\s whitespace
\S non-whitespace
\w word character
\W non-word-character
\d digit
\D non-digit
Ответ 3
Несколько вариантов:
Сопоставьте строку, состоящую из определенного набора символов: ^[a-z]*$
Сопоставьте строку, состоящую из всего, но не определенного набора символов: ^[^a-z]*$
Обратите внимание, что есть несколько ярлыков:
-
\w
: любой буквенно-цифровой символ (включая _
),
-
\w
: любой не-буквенно-цифровой символ;
-
\s
: любой символ пробела,
-
\s
: любой символ без пробелов,
-
\d
: любая цифра,
-
\d
: любая цифра.
Это может стать довольно сложным, например, если вы хотите...
- только не буквы:
[\d_\W]
, или
- только буквы:
[^\d_\W]
(то есть "не цифра, а не _
, а не не буквенно-цифровой символ)
Сопоставьте строку, содержащую подстроку: ^.*substring.*$
Сопоставьте строку, не содержащую подстроку: ^(?:(?!substring).)*$
Обратите внимание, как мы должны проверять каждую позицию в строке для "отсутствия присутствия" подстроки. Вы также можете подставить любое регулярное выражение для substring
для соответствия строкам, которые содержат или не содержат определенного подрежима.
Сопоставьте что-нибудь: .*
(если вы хотите также совместить новые строки, вам нужно будет установить соответствующую опцию вашего языка программирования, например, re.DOTALL
в Python)
Сопоставьте что-нибудь, если вы не знаете, как установить эту опцию: [\s\S]*
Никогда не соглашайтесь ни с чем (по какой-либо причине):
-
$^
(то есть совпадение конца строки перед началом строки),
-
\b\B
(соответствует позиции, где есть одновременно граница слова, а не граница слова) или
-
(?!)
(соответствует позиции, где невозможно совместить пустую строку).
Ответ 4
Используя негативный прогноз, вы сможете обрабатывать большинство основных случаев
/(?!(OriginalRegex)).*?/
Ответ 5
Первый пример не имеет смысла, но для второго вы можете использовать отрицание символа класса:
[a-z] --> [^a-z]
Ответ 6
Я пытаюсь понять определение обратного для регулярного выражения.
match (input, regular_expression) = {match1, match2,..., matchN}
Как бы обратная работа? Если это что-то вроде
match (input, inverse_regular_expression) = {imatch1, imatch2,..., imatchN}
Если да, то какова связь между первым набором результатов и вторым? Если нет, то что это такое?