【问题标题】:Emacs Lisp: can the same regexp match two different patterns with same number of groupings?Emacs Lisp:相同的正则表达式可以匹配具有相同数量分组的两个不同模式吗?
【发布时间】:2012-02-02 23:21:49
【问题描述】:

我已经根据http://www.emacswiki.org/emacs/EmacsScripts 给出的说明开始编写 Emacs 脚本,基本上说你的脚本应该以:

:;exec emacs --script "$0" $@ 

现在我想自定义auto-mode-interpreter-regexp' accordingly, to make Emacs scripts automatically loaded withemacs-lisp-mode'。

原来的 `auto-mode-interpreter-regexp' 是为了匹配:

#! /bin/bash
#! /usr/bin/env perl

等等,所以就是这个:

"\\(?:#![   ]?\\([^     \n]*/bin/env[   ]\\)?\\([^  \n]+\\)\\)"

我尝试添加新的正则表达式作为替代:

(setq auto-mode-interpreter-regexp
   (concat ;; match "#! /bin/bash", "#! /usr/bin/env perl", etc.
           "\\(?:#![    ]?\\([^     \n]*/bin/env[   ]\\)?\\([^  \n]+\\)\\)"
           ;; or
           "\\|"
           ;; match ":;exec emacs "
           "\\(?::;[    ]?\\(exec\\)[   ]+\\([^     \n]+\\)[    ]*\\)"))

但是这个匹配整个字符串时,未能捕获其子匹配,尤其是检测解释器所需的第二个。因此,我混合了正则表达式以同时匹配两个标题:

(setq auto-mode-interpreter-regexp
    (concat ;; match "#!" or ":;"
            "\\(?:#!\\|:;\\)"
            ;; optional spaces
            "[  ]?"
            ;; match "/bin/bash", "/usr/bin/env" or "exec" 
            "\\(\\[^    \n]*/bin/env[   ]\\|exec[   ]\\)?"
            ;; match interpreter
            "\\([^  \n]+\\)"))

我可以做得更好吗?谢谢。

【问题讨论】:

    标签: regex emacs elisp


    【解决方案1】:

    Emacs 中的正则表达式支持使用“显式编号组”构造来为任何子匹配分配组编号。见Elisp Manual 34.3.1.3 Backslash Constructs in Regular Expressions

    语法为‘(?num: ... )’,其中num 是所选组号。

    【讨论】:

    • 哦,是的,我完全忘记了这一点。好电话,怀远!
    【解决方案2】:

    正则表达式的分组由出现在其中的括号定义。这就是为什么您的三个正则表达式中的第二个匹配但不能在这种情况下使用:“exec”和“emacs”分别在第 3 组和第 4 组中捕获,但 auto-mode-interpreter-regexp 期望脚本解释器的名称在第 2 组中。

    (编辑:我上面写的内容是错误的,除了第 2 组与auto-mode-interpreter-regexp 的相关性。有关见解,请参阅怀远的答案。)

    来自所述变量的文档:

    正则表达式匹配解释器,用于文件模式确定。这 正则表达式与文件的第一行匹配以 在“set-auto-mode”中确定文件的模式。如果匹配,则文件 假定由第二个匹配的解释器解释 正则表达式组。

    我认为您的最终解决方案看起来相当不错。两个cmets:

    1. 原始的正则表达式包含在\\(?:...\\) 中。这对匹配本身没有影响,但是如果您将它与其他正则表达式结合使用,则在附加后缀运算符的情况下可能会有所帮助:

      (setq my-regexp (concat auto-mode-interpreter-regexp "?"))

    2. 您的正则表达式现在也匹配 #!exec... 之类的内容,这可能不是问题。出现这种情况是因为您考虑了 shebang,这是正确的做法,因为 (match-string 1) 是分别匹配 (/usr)/bin/envexec,而不包括 shebang。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-25
      • 1970-01-01
      • 2019-07-13
      • 2015-03-04
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      相关资源
      最近更新 更多