我在尝试创建一个排除组的 Emacs 正则表达式时遇到了困难。
[^]
排除集合中的单个字符,但我想排除特定的 sequences 字符:类似 [^(not|this)]
之类的东西,以便包含“not”或“this”的字符串不匹配。
原则上,我可以写
([^n][^o][^t]|[^...])
,但是还有其他更干净的方法吗?
这并不容易实现。正则表达式旨在匹配事物,这就是它们所能做的。
首先:
[^]
不指定“排除组”,它指定否定的字符类。字符类不支持任何形式或形状的分组。它们支持单个字符(为了方便起见,还支持字符范围)。就正则表达式引擎而言,您的尝试 [^(not|this)]
100% 相当于 [^)(|hinots]
。
三种方法可以摆脱这种情况:
(not|this)
和排除借助您所在环境的任何匹配(否定匹配结果)首先:
[^n][^o][^t]
不是解决方案。这还会排除诸如 nil
([^n]
不匹配)、bob
([^o]
不匹配)或 cat
([^t]
不匹配)之类的单词。
但是可以使用基本语法构建一个正则表达式,该正则表达式确实匹配既不包含
not
也不包含 this
的字符串:
^([^nt]|n($|[^o]|o($|[^t]))|t($|[^h]|h($|[^i]|i($|[^s]))))*$
此正则表达式的模式是允许任何不是单词第一个字符或仅单词前缀而不是整个单词的字符。
很难相信接受的答案(来自 Gumbo)实际上被接受了!除非它被接受,因为它表明你“不能”做你想做的事。除非你有一个函数可以生成这样的正则表达式(如 Gumbo 所示),否则编写它们将是一件非常痛苦的事情。 真正的用例是什么——你真正想要做什么?
正如 Tomalak 所指出的,(a) 这不是正则表达式所做的; (b) 请参阅他链接到的其他帖子,以获得更好的解释,包括如何解决您的问题。
答案是使用正则表达式来匹配您想要的
不想要的内容,然后从初始域中减去它。 IOW,不要尝试让正则表达式进行排除(它不能);使用正则表达式进行排除after以匹配您要排除的内容。 这就是每个使用正则表达式的工具的工作原理(例如,
grep
):它们提供了一个单独的选项(例如通过语法)来执行减法——在匹配需要减去的内容之后。
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,用于根据当前缓冲区编写正则表达式。
;; 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
我使用这种方法来避免我讨论的函数的错误在这里
delete-lines
解决方案是传递正则表达式 M-x
keep-lines