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

Any*_*orn 24 regex emacs elisp regex-negation regex-group

我难以设法创建一个排除组的Emacs正则表达式.[^]排除集合中的单个字符,但我想排除特定的字符序列:类似的东西[^(not|this)],以便包含"not"或"this"的字符串不匹配.

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

Tom*_*lak 25

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

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

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

  1. 借助您所处的环境匹配(not|this)排除任何匹配(否定匹配结果)
  2. 使用负前瞻,如果你的正则表达式引擎支持并且在这种情况下可行
  3. 重写表达式以使其匹配:请参阅我之前提到的类似问题

  • 我不知道为什么这个答案这么低,这是这里最清楚的答案! (2认同)

Gum*_*mbo 16

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

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

^([^nt]|n($|[^o]|o($|[^t]))|t($|[^h]|h($|[^i]|i($|[^s]))))*$
Run Code Online (Sandbox Code Playgroud)

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

  • +1,如果我曾经试图切换到Emacs,这就足够了.任何人*如何*没有前瞻的生活*?:P (17认同)
  • 到目前为止,我非常喜欢Emacs,这是我的第一个“什么……” (3认同)

Dre*_*rew 13

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

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

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

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

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


cat*_*ive 9

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

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

所以例如,匹配这个javascript函数的主体:

bar = function (args) {
    if (blah) {
        foo();
    }
};
Run Code Online (Sandbox Code Playgroud)

你可以使用这个emacs正则表达式:

function ([^)]+) {[[:ascii:]]+?};
Run Code Online (Sandbox Code Playgroud)

一旦我们找到两个元素序列"};",我们就停止了.[[:ascii:]]用于"."的instad.运算符,因为它适用于多行.

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

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

作为旁注,如果您编写任何类型的emacs正则表达式,请务必调用Mx重构器,这将带来一个用于针对当前缓冲区编写正则表达式的IDE.


off*_*by1 6

尝试Mx冲洗线.