Emacs Lisp:以紧凑的方式匹配重复的模式?

Ele*_*ena 5 regex emacs elisp

假设我有一个RGB字符串(格式:#<2个十六进制数字> <2个十六进制数字> <2个十六进制数字>),如下所示:

"#00BBCC"
Run Code Online (Sandbox Code Playgroud)

而且我希望以比使用显而易见的方式更紧凑的方式匹配并捕获其<2个十六进制数字>元素:

"#\\([[:xdigit:]\\{2\\}]\\)\\([[:xdigit:]\\{2\\}]\\)\\([[:xdigit:]\\{2\\}]\\)"
Run Code Online (Sandbox Code Playgroud)

我试过了:

"#\\([[:xdigit:]]\\{2\\}\\)\\{3\\}"
Run Code Online (Sandbox Code Playgroud)

和:

"#\\(\\([[:xdigit:]]\\{2\\}\\)\\{3\\}\\)"
Run Code Online (Sandbox Code Playgroud)

但它们匹配的最多是第一个<2个十六进制数字>元素.

任何的想法?谢谢.

Sea*_*ean 5

您可以使regexp变短,但要花一些额外的代码:

(defun match-hex-digits (str)
  (when (string-match "#[[:xdigit:]]\\{6\\}" str)
    (list (substring (match-string 0 str) 1 3)
          (substring (match-string 0 str) 3 5)
          (substring (match-string 0 str) 5 7))))
Run Code Online (Sandbox Code Playgroud)

  • 为什么不呢((let(xx“ \\([[:xdigit:]] \\ {2 \\} \\)”)(string-match(concat“#” xx xx xx)str)))`? (4认同)

Tho*_*mas 3

如果您想捕获不同子组中的 R、G、B,以便可以使用 提取它们(match-string group),则需要在正则表达式中的某个时刻拥有三个不同的括号组。

\(...\)\(...\)\(...\)
Run Code Online (Sandbox Code Playgroud)

否则,如果您使用重复模式,例如

\(...\)\{3\}
Run Code Online (Sandbox Code Playgroud)

你只有一个组,并且在比赛结束后它只会包含最后一场比赛的值。所以,如果你有类似的东西

\([[:xdigit:]]\{2\}\)\{3\}
Run Code Online (Sandbox Code Playgroud)

它将匹配像“A0B1C2”这样的字符串,但(match-string 1)只包含最后一个匹配的内容,即“C2”,因为正则表达式只定义了一组。

因此,您基本上有两个选择:使用紧凑的正则表达式,例如您的第三个,但按照肖恩的建议进行更多子字符串处理以提取十六进制数字,或者使用更复杂的正则表达式,例如您的第一个,它可以让您访问三分比赛更加方便。

如果您最担心代码的可读性,您总是可以这样做

(let ((hex2 "\\([[:xdigit:]]\\{2\\}\\)"))
  (concat "#" hex2 hex2 hex2))
Run Code Online (Sandbox Code Playgroud)

按照 Tripleee 的建议,以一种不太冗余的方式构造这样一个更复杂的正则表达式。