emacs regexp里的"?:"匹配什么?

我看到regex-opt输出的正则表达式很多总会带上?:,但是我们自己写的却一般不会带

谢谢各位

直觉告诉我,你这个问题应该rtfm

我读了……但是没读懂……也可能是因为我没看原文吧。

*** “?:…” “谨慎的”分组(“shy” group), 这个分组不记录匹配的子串;你不能用“\D”来 引用 。这在机械的结合正则表达式的时候有用,这样,你可以为语法目的加入分组,而不用干涉使用者写的分组的个数。

网上随便搜索到的,最早是为了看懂 yasnippet 的代码,里面有个 ?1: ,我至今不知道啥意思


(?:pattern) 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。
	        这对于用"or"字符 (|) 组合模式部件的情况很有用。
	        例如,'industr(?:y|ies) 是比 'industry|industries' 更经济的表达式。

(?=pattern) 执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。
	        它是一个非捕获匹配,即不能捕获供以后使用的匹配。
		    例如,'Windows (?=95|98|NT|2000)' 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。
		    预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

(?!pattern) 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。
	        它是一个非捕获匹配,即不能捕获供以后使用的匹配。
		    例如,'Windows (?!95|98|NT|2000)' 匹配"Windows 3.1"中的 "Windows",但不匹配"Windows 2000"中的"Windows"。
		    预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
1 个赞

让正则解析器把里面的括号内字符当成“一个”字符来解析。

乍一看乍好像没有什么用,但是假如你要匹配emacs字符3到5次,就可以用(?:emacs){3,5}进行匹配。

话说回来,自从发现了rxmacro,我就从来不自己写正则表达式

1 个赞

估计你想说的是 \(?: ... \),这叫做 「Shy Group」,是普通分组 \( ... \) 的退化版本,表示分组但不编号。regexp-opt 默认加这个,因为常常更符合需要:

(concat (regexp-opt '("vim")) "?")
;; 匹配 vim 而不是 vi

?: 的意思就是:匹配,但不捕获。以下例子,加了 ?: 的 group1 为 nil:

(--map (if (string-match "^\\(?:bar\\|foo\\)" it) `(:group0 ,(match-string 0 it) :group1 ,(match-string 1 it)))
       '("foo111"
         "bar222"))
;; => ((:group0 "foo" :group1 nil)
;;     (:group0 "bar" :group1 nil))

(--map (if (string-match "^\\(bar\\|foo\\)" it) `(:group0 ,(match-string 0 it) :group1 ,(match-string 1 it)))
       '("foo111"
         "bar222"))
;; => ((:group0 "foo" :group1 "foo")
;;     (:group0 "bar" :group1 "bar"))

有些编程语言里译作“零宽断言”、“环视”,emacs 里叫“shy group”?…其实都是一个意思。至少从楼上一些信息看来,就是如此。

建议把正则表达式好好学一下,比折腾某些 bug 比 feature 还多的插件有用。

1 个赞

能详细讲讲 rx macro吗?没有搜到相关的内容

零宽断言和shy group不是一个东西……哦它们的写法有点像。


如果你会中文,那正则只要看这一篇文章就够:

感谢……紫薯布丁

感谢指正。看到 @zmqclee 的回答,想到零宽上去了。但两者确实有细微的不同。

写法很像,都用括号;都不编号,无法 backref。尽管多放一起讲,但概念上其实是分开的。