Как мне написать регулярное выражение, которое исключает, а не соответствует, например, not (this|string)?

StackOverflow https://stackoverflow.com/questions/2217928

Вопрос

Я в тупике, пытаясь создать регулярное выражение Emacs, которое исключает группы. [^] исключает отдельные символы в наборе, но я хочу исключить конкретные последовательности из символов:что -то вроде [^(not|this)], так что строки, содержащие "not" или "this", не совпадают.

В принципе, я мог бы написать ([^n][^o][^t]|[^...]), но есть ли другой способ, который был бы чище?

Это было полезно?

Решение

Прежде всего: [^n][^o][^t] это не решение.Это также исключит такие слова, как nil ([^n] не совпадает), bob ([^o] не совпадает) или cat ([^t] не совпадает).

Но можно создать регулярное выражение с базовым синтаксисом, которое будет соответствовать строкам, не содержащим not ни this:

^([^nt]|n($|[^o]|o($|[^t]))|t($|[^h]|h($|[^i]|i($|[^s]))))*$

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

Другие советы

Это нелегко.Регулярные выражения предназначены для соответствовать вещи, и это все, что они могут сделать.

Прежде всего: [^] не обозначает «исключаемую группу», он обозначает отрицательный класс символов.Классы символов не поддерживают группировку в любой форме.Они поддерживают отдельные символы (и, для удобства, диапазоны символов).Ваша попытка [^(not|this)] на 100% эквивалентно [^)(|hinots], что касается механизма регулярных выражений.

Из этой ситуации могут выйти три пути:

  1. соответствовать (not|this) и исключать любые совпадения с помощью среды, в которой вы находитесь (инвертировать результаты совпадений)
  2. используйте отрицательный просмотр вперед, если это поддерживается вашим механизмом регулярных выражений и возможно в данной ситуации.
  3. перепишите выражение так, чтобы оно могло соответствовать:видеть аналогичный вопрос, который я задавал ранее

Трудно поверить, что принятый ответ (от Гамбо) действительно был принят!Если только оно не было принято, потому что оно указывало, что вы не могу делай что хочешь.Если у вас нет функции, генерирующей такие регулярные выражения (как показывает Гамбо), их составление будет настоящей болью.

Каков реальный вариант использования — что вы на самом деле пытаетесь сделать?

Как указал Томалак, (а) это не то, что делают регулярные выражения;(б) см. другой пост, на который он ссылается, для получения хорошего объяснения, в том числе того, что делать с вашей проблемой.

Ответ заключается в использовании регулярного выражения, соответствующего тому, что вы делаете. нет хотите, а затем вычтите это из исходного домена.IOW, не пытайтесь заставить регулярное выражение выполнять исключение (оно не может);сделать исключение после используя регулярное выражение для соответствия тому, что вы хотите исключить.

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

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

Emacs не поддерживает предварительный просмотр напрямую, но он поддерживает нежадную версию *, + и ?операторы (*?, +?, ??), которые в большинстве случаев могут использоваться для той же цели.

Так, например, чтобы соответствовать телу этой функции javascript:

bar = function (args) {
    if (blah) {
        foo();
    }
};

Вы можете использовать это регулярное выражение emacs:

function ([^)]+) {[[:ascii:]]+?};

Здесь мы останавливаемся, как только находим последовательность из двух элементов "};".[[: ascii:]] используется вместо оператора ".", поскольку он работает над несколькими строками.

Это немного отличается от негативного взгляда, потому что };сама последовательность соответствовала, однако, если ваша цель состоит в том, чтобы извлечь все до этого момента, вы просто используете группу захвата \(и \).

Смотрите руководство по регулярным выражениям emacs: http://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html

В качестве дополнительного примечания, если вы пишете какое-либо регулярное выражение emacs, обязательно вызовите M-x re-builder, который откроет небольшую среду IDE для записи вашего регулярного выражения в текущий буфер.

Попробуйте промывочные линии M-x.

В случае использования сопоставления строки для логического теста я делаю это:

;; Code to match string ends with '-region' but excludes those that has 'mouse'.
M-x ielm RET
*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (setq str1 "mouse-drag-region" str2 "mou-drag-region" str3 "mou-region-drag")
"mou-region-drag"
ELISP> (and (string-match-p "-region$" str1) (not (string-match-p "mouse" str1)))
nil
ELISP> (and (string-match-p "-region$" str2) (not (string-match-p "mouse" str2))) 
t
ELISP> (and (string-match-p "-region$" str3) (not (string-match-p "mouse" str3)))
nil

Я использую этот подход, чтобы избежать ошибки в обсуждаемой мной функции. Здесь:

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top