Answers:
首先,请注意,单个斜杠匹配太多:
$ echo $'eegg \n e.g.' | grep e\.g\.
eegg
e.g.
就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\\\\.
$
当Bash看到一个双斜杠时,将其减为一个斜杠并将其传递给grep,在上面的三个测试中的第一个测试中,grep根据需要在一个句点之前看到一个单斜杠。因此,这做对了。
使用三斜杠,Bash将前两个斜杠减少为一个斜杠。然后看到\.。由于转义期对Bash没有特殊意义,因此可以将其缩短为简单期。结果是,grep在我们想要的时候在句号之前看到了一个斜线。
通过四个斜杠,Bash将每对减为一个斜杠。Bash传递给grep两个斜杠和一个句点。grep看到两个斜杠和一个句点,并将两个斜杠减少为单个文字斜杠。除非输入的文字斜杠后跟任何字符,否则没有匹配项。
为了说明最后一点,请记住在单引号内所有字符都是文字。因此,给定以下三行输入,grep命令仅在输入中带有文字斜杠的行上匹配:
$ echo 'eegg
e.g.
e\.g\.' | grep e\\\\.g\\\\.
e\.g\.
对于Bash,规则是
两个斜杠减少为一个斜杠。
普通字符前面的斜线(例如句点)只是普通字符(句号)。
从而:
$ echo \. \\. \\\. \\\\.
. \. \. \\.
有一种避免所有这些混乱的简单方法:在Bash命令行上,正则表达式应放在单引号中。在单引号内,Bash保留所有内容。
$ echo '\. \\. \\\. \\\\.' # Note single-quotes
\. \\. \\\. \\\\.
echo说明在这些情况下bash的功能的声明。
\.或.。对于bash来说,两者是相同的:它们相当于一个普通的时期。因此,总的来说,bash传递给grep的两者是相同的:单斜杠后跟一个句点。
echo由于该程序的许多实现,因此使用不是测试regexp的可靠方法。例如在我的zsh(内置echo)下echo \. \\. \\\. \\\\. \\\\\.给出. \. \. \. \.,但/bin/echo \. \\. \\\. \\\\. \\\\\.返回. \. \. \\. \\.。喜欢的东西printf "%s" ...可能是更好的办法。
输出仅对于您的字符串是相同的,但是通常那些正则表达式执行不同的操作。让我们通过添加第二个图案e,g,(带逗号),第三个e\.g\.(点),第四个e\,g\,(逗号)和-ogrep选项(仅打印匹配的部分)来对示例进行一些修改。
在以下情况下.(通知匹配任何字符''左右e.g.,以后我会走到那)
$ grep -o 'e.g.' <<< grep -o 'e.g.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e.g.
e,g,接下来,我们.使用反斜杠进行转义\,因此.将仅匹配文字:
$ grep -o 'e\.g\.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e.g.但是我们可以\使用another 来转义\,这样文字\将匹配后跟.(即任何char):
$ grep -o 'e\\.g\\.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e\.g\.
e\,g\,但是,如果我们想只匹配\.不\,那么又\需要逃脱点的特殊含义:
$ grep -o 'e\\\.g\\\.' <<< 'this is an e.g. e,g, e\.g\. e\,g\,'
e\.g\.现在,因为您没有''在grep参数周围使用,所以您需要添加另一个反斜杠来避免反斜杠从shell解释中退出,因此:
grep 'e\.g\.' => grep e\\.g\\.
grep 'e\\.g\\.' => grep e\\\\.g\\\\. (each backslash has to be quoted separately)
grep 'e\\\.g\\\.' => grep e\\\\\\.g\\\\\\. (3 x 2 = 6 backslashes in total)
当您执行时grep e\.g\.,shell会消耗反斜杠,因此您正在执行grep e.g.,该匹配。当您执行时grep e\\.g\\.,shell再次使用斜杠,而现在您正在执行grep e\.\g.,再次匹配。现在,外壳的反斜杠看起来像\\。因此,当具有时\\,第一个是转义序列,第二个是文字反斜杠。当您执行a时grep e\\\.g\\\.,它仍然最终会存在grep e\.\g.,因为\在第一个\将其变为文字之前没有转义序列()\。请记住\是一个反斜杠,因此grep e\\\\.\\\\g最终成为grep e\\.g\\.,显然不匹配。
要查看外壳如何查看您在做什么,请使用echo(例如echo grep e\\.g\\. <<< "this is an e.g. wow"vs echo grep e\\\\.g\\\\. <<< "this is an e.g. wow")。
这两个命令只为您的输入产生相同的输出,否则它们是不同的。对于什么是对我们怎么理解必须知道如何为参数首先解释bash,然后通过grep。
\是一个特殊字符,它取消了后续字符(包括\其自身)的特殊含义。如果以下字符没有特殊含义,则将其原封不动地传递。命令和结果示例:
echo \a:a-普通字符转义给出字符echo \\:\—转义的特殊字符赋予该字符echo \\\a:\a—特殊组合,普通echo \\\\:\\—特殊组合,特殊echobash解释后将打印结果字符串。更多信息:bash文档,bash黑客Wiki,POSIX规范。
.在中没有特殊含义bash。这是外壳的普通字符。以下是与您的示例相关的序列:
echo .: .echo \.: .echo \\.: \.echo \\\.: \.echo \\\\.: \\.要从字面上传递参数,bash可以使用单引号'转义。在单引号之间,您不必关心字符的特殊含义,因为单引号是唯一具有特殊含义的字符。您可以在将字符串的第一部分括起来之后插入单引号。例如
echo 'part1'\''part2': part1'part2
\是转义字符,含义与中的相似bash。.是一个特殊字符,表示任何字符的一次出现。请参阅:POSIX regex,GNU grep regex。正则表达式的示例:
.—匹配任何字符,例如a或.\.—仅从.字面上匹配在下面每个示例的第二行,您都将找到等效的单引号',该单引号显示了传递bash给的文字字符串grep。然后,在grep执行转义后,示例中唯一可能的特殊字符.与任何字符都匹配。第三行上有一个表达式匹配的描述。
grep e.g. <<< "this is an e.g. wow"grep 'e.g.' <<< "this is an e.g. wow"e任何字符g任何字符 - 匹配e.g.,可能还包含其他字符串,例如eagbgrep e\.g\. <<< "this is an e.g. wow"grep 'e.g.' <<< "this is an e.g. wow"e任何字符g任何字符 - 匹配e.g.,可能还包含其他字符串,例如exgygrep e\\.g\\. <<< "this is an e.g. wow"grep 'e\.g\.' <<< "this is an e.g. wow"e.g.从字面上看- 仅匹配e.g.grep e\\\.g\\\. <<< "this is an e.g. wow"grep 'e\.g\.' <<< "this is an e.g. wow"e.g.从字面上看- 仅匹配e.g.grep e\\\\.g\\\\. <<< "this is an e.g. wow"grep 'e\\.g\\.' <<< "this is an e.g. wow"e\任何字符g\任何字符 - 不匹配e.g.
\\\.grep并给予\.它,但事实并非如此。好问题