在emacs的“自定义”模式中,为了转义正则表达式需要多少个反斜杠?

9

我正在尝试使用emacs的customize-group包来调整我的设置,但我却碰到了瓶颈。在使用customize后,我会在我的.emacs文件中看到以下类似的内容:

'(tramp-backup-directory-alist (quote (("\\\\`.*\\\\'" . "~/.emacs.d/autobackups"))))

这是将以下内容放入自定义文本字段的结果:
Regexp matching filename: \\`.*\\'

这是一个代表性的例子:我实际上正在尝试更改几个需要正则表达式的东西,它们都显示出了同样的问题。引用层数到底有多少?我似乎找不到魔法数字来让它做我要求的事情,即使对于最简单的正则表达式如.*。现在,给定的自定义不会产生任何结果。它与emacs的默认行为没有任何变化。
更好的方法是,在哪里可以找到文档?这有点难以搜索,但我已经尝试了很多东西,包括官方文档和Emacs维基。在哪里可以找到权威来源,告诉我们需要多少反斜杠才能使customize-mode中的正则表达式实际工作-或者至少失败时发出某种警告而不是默默失败?
编辑:常常在愤怒中提出问题时,我问错了问题。幸运的是,下面的答案引导我找到了我需要的答案,那就是关于引用规则的问题。我要试着把我在这里学到的东西写下来,因为我发现文档和可搜索资源在这方面非常模糊。所以,以下是我通过试错找到的引用规则,希望能帮助其他人,激发更正,或两者兼备。

当emacs customize-mode缓冲区要求您输入“与文件名匹配的正则表达式”时,它既简洁又特殊(通常创作者的个性会被赋予到创作中!)。它意味着,首先,一个正则表达式将与整个文件路径进行比较,以寻找匹配项,而不仅仅是像“filename”这个术语所暗示的那样只与文件名本身进行比较。例如,在emacs的buffer-file-name函数中使用了相同的“filename”意义。

此外,尽管如果您在字段中放置 foo ,则会看到“foo”(带双引号)写入实际文件,但这不足够引用也不是正确的引用。您需要使用引用样式对正则表达式进行引用,据我所知,只有emacs使用:`` backtick-foo-single-quote'`方案。然后,您需要转义它,使其变为 \`backslash-backtick-foo-backslash-single-quote\' (如果您认为在Markdown中输入这个头痛,那么在emacs中更加如此)。

除此之外,emacs似乎有一个规则,即 regexp特殊字符不匹配以/开头的文件名,因此,就像上面发生的那样,经典的 .* 模式似乎不匹配任何内容:要匹配“所有文件”,实际上您需要使用regexp /。*,然后将其塞入customize-mode的引号格式中以生成 \`/.*\',之后customize会在其上涂上另一层转义并将其写入自定义文件。 我为之努力的最终结果是这样的一个设置:#自动保存#文件不会混乱地堆积在你正在工作的目录中,而是都存放在同一个地方。

(custom-set variables
  '(auto-save-file-name-transforms (quote (
    ("\\`/[^/]*:\\([^/]*/\\)*\\([^/]*\\)\\'" "~/.emacs.d/autobackups/\\2" t)
    ("\\`/.*/\\(.*?\\)\\'" "~/.emacs.d/autobackups/\\1" t)
))))

在elisp中,反斜杠比括号更容易让你发疯。
编辑2:我又错了。我终于找到了相关文档(当然是通过阅读另一个Stack Overflow问题!):正则表达式反斜杠构造。对我而言混淆的关键点是:在这个上下文中,反引号和单引号并没有引用的作用:它们相当于Perl的^$特殊字符。反斜杠-反引号结构匹配以空字符串为锚定点的字符串开头,在所考虑的字符串末尾处匹配空字符串。而“所考虑的字符串”指的是“缓冲区”,在这种情况下,缓冲区恰好只包含文件路径,但如果您想要匹配,就需要匹配整个字符串,因为这是elisp的全局正则表达式行为。

发誓,这就像在处理外星文明一样。


编辑3: 为了避免混淆未来的读者 -

  • \` 是emacs正则表达式中"缓冲区的开头"的意思。(参考 Perl的\A)
  • \' 是emacs正则表达式中"缓冲区的结尾"的意思。(参考Perl的\Z)
  • ^ 是常用的正则表达式,表示"行的开头"。它可以在emacs中使用。
  • $ 是常用的正则表达式,表示"行的结尾"。它可以在emacs中使用。
因为在Emacs中跨多行文本进行正则表达式搜索比其他地方(例如,M-x occur)更常见,所以在Emacs中使用反引号和单引号特殊字符。据我所知,在customize-mode上下文中使用它们是因为如果您考虑到一个customize-mode字段的通用未知输入可能包含换行符,因此希望使用缓冲区开头和缓冲区结尾的特殊字符,因为输入的开头和结尾不能保证是一行的开头和结尾。
我不确定是否后悔劫持了自己的Stack Overflow问题,并将其转变为博客文章。

“到达troff宏的中心需要多少反斜杠”和“到达Tootsie-Roll Pop的中心需要舔多少次”这个问题的答案是一样的:不断尝试直到成功为止。 :) - tchrist
加1鼓励你继续坚持并与全世界分享你的发现! :) - itsjeyd
1个回答

3
在自定义字段中,您需要根据此处描述的语法输入正则表达式。当自定义将正则表达式写入字符串中时,正则表达式中的任何反斜杠或双引号字符都会被转义,遵循常规字符串转义约定。
因此,简而言之,在正则表达式字段中只需输入单个反斜杠,它们将在生成的custom-set-variables子句中正确加倍写入您的.emacs
另外:由于您的正则表达式用于匹配文件名,您可以尝试打开包含您想要匹配的文件的目录,然后运行M-x re-builder RET。然后,您可以以字符串转义格式输入正则表达式,以确认它是否匹配这些文件。通过在dired缓冲区中键入% m,您可以以未转义格式(即与自定义字段中完全相同)输入正则表达式,并且dired将标记匹配的文件名。

1
此外,如果您直接评估变量的值(在自定义设置后),您可以确定它是否正确。 - phils
好的建议;M-:是你的好朋友!当然,它也会打印出正则表达式作为一个字符串,包括额外的反斜杠。 - sanityinc
1
很遗憾,您的答案并没有解决我的问题,但是它是第一个友好的答案,并帮助我走上了实际解决问题的道路,所以我接受了它。 - Brighid McDonnell
@centipedefarmer 你能具体说明一下吗? :-) - sanityinc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接