为什么有些正则表达式命令对不同字符的 '\' 有相反的解释?

Cor*_*ein 10 find regular-expression

以这个命令为例:

find . -regex ".*\.\(cpp\|h\)"
Run Code Online (Sandbox Code Playgroud)

这将在您的目录中找到所有 .h 和 .cpp 文件。句点字符“.” 在正则表达式中通常表示“任何字符”。要使其仅匹配实际句点,您必须使用反斜杠字符 '\' 对其进行转义。

在这种情况下,给定一个具有特殊含义的字符,您必须对其进行转义以获取它所代表的实际字符。

现在,取括号和“或”栏,分别是字符 '(', ')' 和 '|'。这些也有特殊含义,用于对正则表达式进行分组。但是,要获得特殊含义,必须使用反斜杠对字符进行转义!没有反斜杠,字符具有它所代表的实际字符的含义。

为什么是“.” 与 '(', ')' 和 '|' 区别对待?

mat*_*tdm 12

答案真的是“只是因为”。有一大堆不同的正则表达式语法,虽然它们具有相似的外观并且通常基础是相同的,但它们的细节却有所不同。

从历史上看,每个工具都有自己的新实现,可以做作者认为最好的事情。在使字符特殊和不转义之间有一个平衡——太多“自然特别”的字符,你最终不得不一直逃避它们只是为了匹配它们;或者,反过来说,你最终需要一堆转义符来使用常见的正则表达式语法,比如 () 分组。每个编写程序的人都根据他们的程序所匹配的需求、他们认为正确的方法以及月相来决定如何去做。

POSIX 尝试标准化,它定义了“基本正则表达式”和“扩展正则表达式”。令人惊叹的是,这些工作在\-有时,但并非完全一致。

Perl 正则表达式已经成为另一个事实上的标准,有两个原因:首先,它们非常灵活和强大,其次,它们实际上非常理智,具有诸如“\ 总是转义非字母数字字符”之类的约定。

GNU Find 有一个-regextype选项,您可以在其中更改使用的正则表达式语法。可悲的是,“perl”不是一个选项,至少在我拥有的 find 版本中。(毫不奇怪,默认值来自 GNU,“emacs”,该语法记录在此处。)