如何编写一个排除而不是匹配的正则表达式,例如,不是(this | string)?

时间:2010-02-07 19:16:42

标签: regex emacs elisp regex-negation regex-group

我难以尝试创建一个排除群组的Emacs正则表达式。 [^]排除集合中的单个字符,但我想排除字符的特定序列:类似于[^(not|this)],因此包含“not”或“this”的字符串不是匹配。

原则上,我可以写([^n][^o][^t]|[^...]),但还有另一种更清洁的方法吗?

8 个答案:

答案 0 :(得分:23)

这不容易实现。正则表达式旨在匹配事物,这就是他们所能做的。

首先关闭:[^]不指定“排除组”,它指定一个否定的字符类。字符类不支持任何形式或形状的分组。它们支持单个字符(为方便起见,还支持字符范围)。就正则表达式引擎而言,您的尝试[^(not|this)] 100%相当于[^)(|hinots]

有三种方法可以摆脱这种情况:

    借助您所处的环境
  1. 匹配(not|this)排除任何匹配项(取消匹配结果)
  2. 使用负面预测,如果你的正则表达式引擎支持并且在这种情况下可行
  3. 重写表达式以便匹配:请参阅a similar question I asked earlier

答案 1 :(得分:16)

首先:[^n][^o][^t]不是解决方案。这也会排除nil[^n]不匹配),bob[^o]不匹配)或cat[^t]不匹配)。

但是可以使用基本语法构建一个正则表达式,该语法匹配既不包含not也不包含this的字符串:

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

这个正则表达式的模式是允许任何不是单词的第一个字符或仅单词的前缀而不是整个单词的字符。

答案 2 :(得分:13)

很难相信接受的答案(来自Gumbo)实际上已被接受!除非它被接受,因为它表明你不能做你想做的事。除非你有一个生成这种正则表达式的函数(如Gumbo所示),否则编写它们将是一个真正的痛苦。

真实用例是什么 - 你真正想做什么?

正如托马拉克所指出的,(a)这不是正规则所做的; (b)查看他所关联的另一篇文章,以获得一个很好的解释,包括如何处理你的问题。

答案是使用正则表达式来匹配想要的内容,然后从初始域中减去它。 IOW,不要试图让regexp做排除(它不能); 之后使用正则表达式排除以匹配您要排除的内容。

这是使用正则表达式的每个工具的工作原理(例如,grep):它们提供了一个单独的选项(例如通过语法)来执行减法 - 在匹配需要减去的内容之后。

答案 3 :(得分:9)

听起来你正试图做出负面的预测。即,一旦达到某个分隔符,就会尝试停止匹配。

Emacs不直接支持lookahead,但它确实支持*,+和?的非贪婪版本。运算符(*?,+?,??),在大多数情况下可以用于相同的目的。

例如,要匹配此javascript函数的主体:

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

您可以使用此emacs正则表达式:

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

一旦我们找到两个元素序列“};”,我们就停止了。 [[:ascii:]]用于“。”的instad。运算符,因为它可以在多行上运行。

这与负面前瞻略有不同,因为};序列本身它匹配,但是如果你的目标是提取所有内容直到那一点,你只需使用一个捕获组\(和\)。

请参阅emacs正则表达式手册:http://www.gnu.org/software/emacs/manual/html_node/emacs/Regexps.html

作为旁注,如果您编写任何类型的emacs正则表达式,请务必调用M-x重建器,这将启动一个小IDE,用于针对当前缓冲区编写正则表达式。

答案 4 :(得分:6)

尝试M-x冲洗线。

答案 5 :(得分:2)

对于匹配字符串进行逻辑测试的用例,我这样做:

;; 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

我使用这种方法来避免我讨论过的函数的错误Over Here

答案 6 :(得分:0)

如果您尝试使用正则表达式查找或替换缓冲区中的文本,则可以使用https://github.com/benma/visual-regexp-steroids.el/

可视化正则表达式类固醇允许您使用python regex进行替换,搜索等。 Python regex支持否定前瞻和否定后瞻。

答案 7 :(得分:0)

我的问题是如何将否定的正则表达式传递给 delete-lines 解决方案是传递正则表达式 M-x keep-lines