使用 \\ 与使用 \ 的正则表达式

Wya*_*ant 10 shell bash quoting regular-expression

为什么

grep e\\.g\\. <<< "this is an e.g. wow"
Run Code Online (Sandbox Code Playgroud)

grep e\.g\. <<< "this is an e.g. wow"
Run Code Online (Sandbox Code Playgroud)

做同样的事?

如果我添加第三个斜杠,它也有相同的结果。但是,一旦我添加了第四个斜线,它就不再起作用了。这与一个班级旧考试中的问题有关。它询问带有两个反斜杠的一个是否可以输出带有“eg”的行,我最初认为它不起作用,但我试图确定并且确实如此。解释是什么?

Joh*_*024 9

首先,请注意单斜杠匹配太多:

$ echo $'eegg \n e.g.' | grep e\.g\.
eegg
 e.g.
Run Code Online (Sandbox Code Playgroud)

Bash而言,转义句点与句点相同。Bash 将句号传递给grep。对于 grep,句点匹配任何内容。

现在,考虑:

$ echo $'eegg \n e.g.' | grep e\\.g\\.
 e.g.
$ echo $'eegg \n e.g.' | grep e\\\.g\\\.
 e.g.
$ echo $'eegg \n e.g.' | grep e\\\\.g\\\\.
$
Run Code Online (Sandbox Code Playgroud)

当 Bash 看到双斜线时,它会将其减少为单斜线并将其传递给 grep,在上述三个测试中的第一个测试中,如我们所愿,在句点之前看到一个单斜线。因此,这是正确的。

通过三重斜线,Bash 将前两个斜线减少为一个斜线。然后它看到\.。由于转义句点对 Bash 没有特殊意义,因此将其简化为普通句点。结果是 grep 如我们所愿,在句点前看到一个斜线。

Bash 使用四个斜线将每一对减少为一个斜线。Bash 传递给 grep 两个斜杠和一个句点。的grep看到两条斜线和一个周期,并降低了两个斜杠到单个字面斜线。除非输入有一个斜杠后跟任何字符,否则没有匹配项。

为了说明最后一点,请记住在单引号内,所有字符都是字面量。因此,给定以下三个输入行,grep 命令仅匹配输入中带有斜杠的行:

$ echo 'eegg
e.g.
e\.g\.' |  grep e\\\\.g\\\\.
e\.g\.
Run Code Online (Sandbox Code Playgroud)

Bash 行为总结

对于 Bash,规则是

  • 两个斜线减少为一个斜线。

  • 普通字符前面的斜线,如句号,就是普通字符(句号)。

因此:

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

有一个简单的方法可以避免所有这些混淆:在 Bash 命令行中,正则表达式应该放在单引号中。在单引号内,Bash 将所有内容都放在一边。

$ echo '\. \\. \\\. \\\\.'  # Note single-quotes
\. \\. \\\. \\\\.
Run Code Online (Sandbox Code Playgroud)

  • @DanielAmaya 在这两种情况下, bash 都将前两个斜杠减少为一个斜杠。剩下的是`\.` 或`.`。对于 bash,这两者是相同的:它们相当于一个简单的句点。因此,总的来说,bash 传递给 grep 的内容对于两者都是相同的:单斜杠后跟一个句点。 (2认同)