Как написать регулярное выражение, которое исключает, а не совпадение, например, not (this | string)?
Я с трудом пытаюсь создать регулярное выражение Emacs, которое исключает группы. [^]
исключает отдельные символы в наборе, но я хочу исключить определенные последовательности символов: что-то вроде [^(not|this)]
, так что строки, содержащие "not" или "this", не совпадают.
В принципе, я мог бы написать ([^n][^o][^t]|[^...])
, но есть ли другой способ, что очиститель?
Ответы
Ответ 1
Прежде всего: [^n][^o][^t]
не является решением. Это также исключает такие слова, как nil
([^n]
не соответствует), bob
([^o]
не соответствует) или cat
([^t]
не соответствует).
Но можно создать регулярное выражение с базовым синтаксисом, который соответствует строкам, которые не содержат not
и this
:
^([^nt]|n($|[^o]|o($|[^t]))|t($|[^h]|h($|[^i]|i($|[^s]))))*$
Шаблон этого регулярного выражения должен позволять любому символу, который не является первым символом слов или только префиксами слов, но не целыми словами.
Ответ 2
Это невозможно. Регулярные выражения предназначены для соответствия вещам, и это все, что они могут сделать.
Во-первых: [^]
не обозначает "исключает группу", он обозначает отрицательный класс символов. Классы символов не поддерживают группировку в любой форме или форме. Они поддерживают одиночные символы (и, для удобства, диапазоны символов). Ваша попытка [^(not|this)]
соответствует 100% эквиваленту [^)(|hinots]
, что касается двигателя регулярных выражений.
Из этой ситуации могут вывести три способа:
- сопоставить
(not|this)
и исключить любые совпадения с помощью среды, в которой вы находитесь (отрицать результаты сопоставления)
- используйте отрицательный внешний вид, если поддерживается вашим механизмом регулярных выражений и возможно в ситуации
- переписать выражение, чтобы оно могло соответствовать: см. аналогичный вопрос, который я задал ранее
Ответ 3
Трудно поверить, что принятый ответ (от Gumbo) был фактически принят! Если бы это не было принято, потому что оно указывало, что вы не можете делать то, что хотите. Если у вас нет функции, которая генерирует такие регулярные выражения (как показывает Gumbo), составление их будет настоящей болью.
Каков реальный прецедент - что вы действительно пытаетесь сделать?
Как указал Томалак, (а) это не то, что делают регулярные выражения; (б) см. другой пост, с которым он связался, для хорошего объяснения, включая, что делать с вашей проблемой.
Ответ заключается в том, чтобы использовать регулярное выражение для соответствия тому, что вы не хотите, а затем вычесть из исходного домена. IOW, не пытайтесь сделать regexp делать исключение (оно не может); выполните исключение после использования регулярного выражения в соответствии с тем, что вы хотите исключить.
Вот как работает каждый инструмент, использующий регулярные выражения (например, grep
): они предоставляют отдельный параметр (например, через синтаксис), который выполняет вычитание - после сопоставления того, что нужно вычесть.
Ответ 4
Попробуйте флеш-линии M-x.
Ответ 5
Похоже, вы пытаетесь сделать негативный взгляд. т.е. вы пытаетесь остановить совпадение, как только вы достигнете некоторого разделителя.
Emacs не поддерживает lookahead напрямую, но поддерживает не-жадную версию *, + и? операторы (*?, +?,?), которые могут использоваться в той же цели в большинстве случаев.
Так, например, чтобы совместить тело этой функции javascript:
bar = function (args) {
if (blah) {
foo();
}
};
Вы можете использовать это регулярное выражение emacs:
function ([^)]+) {[[:ascii:]]+?};
Здесь мы останавливаемся, когда находим две последовательности элементов "};". [[: ascii:]] используется instad "." потому что он работает на нескольких строках.
Это немного отличается от негативного взгляда, потому что}; сама последовательность соответствует, однако, если ваша цель состоит в том, чтобы извлечь все до этой точки, вы просто используете группу захвата\(и \).
См. руководство emges regex: http://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html
В качестве побочного примечания, если вы пишете какое-либо регулярное выражение emacs, обязательно запустите M-x re-builder, который выведет небольшую среду IDE для записи вашего регулярного выражения в текущий буфер.
Ответ 6
В случае использования строки для логического теста я делаю следующее:
;; 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
Я использую этот подход, чтобы избежать ошибки функции, которую я обсуждал Здесь::