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

问题描述 投票:0回答:9

我在尝试创建一个排除组的 Emacs 正则表达式时遇到了困难。

[^]
排除集合中的单个字符,但我想排除特定的 sequences 字符:类似
[^(not|this)]
之类的东西,以便包含“not”或“this”的字符串不匹配。

原则上,我可以写

([^n][^o][^t]|[^...])
,但是还有其他更干净的方法吗?

regex emacs elisp regex-negation regex-group
9个回答
34
投票

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

首先:

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

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

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

22
投票

首先:

[^n][^o][^t]
不是解决方案。这还会排除诸如
nil
[^n]
不匹配)、
bob
[^o]
不匹配)或
cat
[^t]
不匹配)之类的单词。

但是可以使用基本语法构建一个正则表达式,该正则表达式确实匹配既不包含

not
也不包含
this
的字符串:

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

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


13
投票

很难相信接受的答案(来自 Gumbo)实际上被接受了!除非它被接受,因为它表明你“不能”做你想做的事。除非你有一个函数可以生成这样的正则表达式(如 Gumbo 所示),否则编写它们将是一件非常痛苦的事情。 真正的用例是什么——你真正想要做什么?

正如 Tomalak 所指出的,(a) 这不是正则表达式所做的; (b) 请参阅他链接到的其他帖子,以获得更好的解释,包括如何解决您的问题。

答案是使用正则表达式来匹配您想要的

想要的内容,然后从初始域中减去它。 IOW,不要尝试让正则表达式进行排除(它不能);使用正则表达式进行排除after以匹配您要排除的内容。 这就是每个使用正则表达式的工具的工作原理(例如,

grep

):它们提供了一个单独的选项(例如通过语法)来执行减法——在匹配需要减去的内容之后。

    


10
投票

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 重新构建器,这将打开一个小 IDE,用于根据当前缓冲区编写正则表达式。


7
投票


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

我使用这种方法来避免我讨论的函数的错误
在这里


1
投票
delete-lines

解决方案是传递正则表达式 M-x

keep-lines
    


0
投票
https://github.com/benma/visual-regexp-steroids.el/

Visual regexp steroids 允许您使用 python 正则表达式进行替换、搜索等。 Python 正则表达式支持负向前看和负向后看。


0
投票
keep-lines

将删除当前缓冲区中与给定正则表达式不匹配的所有行,这是引导我进入此页面的用例。

https://www.gnu.org/software/emacs/manual/html_node/emacs/Other-Repeating-Search.html

© www.soinside.com 2019 - 2024. All rights reserved.