2010-02-07 33 views
18

我很难过试图创建一个排除组的Emacs正则表达式。 [^]不包括集合中的单个字符,但我想排除特定的字符序列:类似于[^(not|this)],以便包含“不”或“this”的字符串不匹配。如何编写排除而非匹配的正则表达式,例如not(this | string)?

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

+3

我认为这是GNU ERE。 – Gumbo 2010-02-07 19:19:38

+0

@Gumbo。 你是对的,谢谢 – Anycorn 2010-02-07 19:22:17

+0

点击“regex-negation”标签查看一些类似的问题。 – finnw 2010-02-09 12:59:34

回答

13

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

但它有可能建立与基本语法,做匹配字符串既不包含正则表达式not也不this

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

这个正则表达式的模式是允许不是第一的任何字符字或单词的前缀,但不是全部单词。

+12

+1,如果我曾经试图切换到Emacs,这将是不够的理由。任何人都可以*没有超前视力? :P – 2010-02-07 20:29:00

+1

到目前为止,非常享受Emacs,这是我的第一个“什么......” – biocyberman 2015-08-03 19:57:05

19

这并不容易。正则表达式被设计为匹配的东西,这是他们所能做的。

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

三种方式可以导致了这种情况:

  1. 比赛(not|this)排除任何匹配与你所处的环境的帮助(否定的比赛结果)
  2. 使用负前瞻,通过你的正则表达式引擎,并在情况如果支持的话可行
  3. 重写的表达,因此它可以比赛:看a similar question I asked earlier
+1

我想知道为什么这个答案如此低调地上传,这是最清晰的答案! – 2014-08-04 14:26:22

+0

@Yagamy因为它或多或少说“不起作用”,而显然有一种方法可以使它工作(即使是不切实际的更不得已而为之)。 – Tomalak 2014-08-05 05:24:19

+1

我在这里没有看到“不起作用”的说法,甚至相反:您展示了三种可以解决问题的方式,第三种方式就像接受的答案一样。 – 2014-08-05 11:26:24

6

尝试使用M-x冲洗线。

13

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

什么是真正的用例 - 你真的想要做什么? (a)这不是什么正则表达式所做的; (b)看到他链接的另一篇文章,有一个很好的解释,包括如何解决你的问题。

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

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

6

这听起来像你正在试图做负面的前瞻。即一旦达到某个分隔符,您就试图停止匹配。

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的正则​​表达式时,一定要调用的Mx重新建造,这将带来了一个小的IDE针对写你的正则表达式当前的缓冲区。

1

匹配的逻辑测试字符串的使用情况下,我这样做:

;; 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功能的缺陷: