在 GNU grep 正则表达式中使用引号

use*_*539 5 shell grep bash quoting

我可以看到 GNU Grep 中的某些模式可以包含在括号中,而某些其他模式则不需要。例如,匹配单词的开头只有在它被引号括起来时才有效。

user@host:~/Desktop$ grep -E '\<H' test
Hello World
user@host:~/Desktop$ grep -E \<H test
Run Code Online (Sandbox Code Playgroud)

[测试包含字符串 Hello World]

但是匹配文件的结尾和开头不需要美元:

user@host:~/Desktop$ egrep d$ test
Hello World
Run Code Online (Sandbox Code Playgroud)

为什么会这样?规则是什么?

Gil*_*il' 8

引号由外壳展开,它们决定了grep看到的内容。

使用grep -E '\<H',单引号之间的字符按字面传递,因此 grep 会看到\<H包含单词开头 anchor的正则表达式\<

使用grep -E \<H,反斜杠字符删除<了 shell中的特殊含义,并grep看到了正则表达式<H。您会看到类似<Hello>.

使用grep -E <H,该<字符将在 shell 中作为重定向字符具有其特殊含义,因此grep将接收H在其标准输入上调用的文件的内容。

使用grep 'd$'or grep d\$,引用美元符号,使其达到grep: 正则表达式为d$,匹配d行尾的 a 。

对于grep d$ test$符号后面没有有效的变量名或有效的标点符号 ( ${, $()。发生这种情况时,shell 会$逐字传递符号,因此grep再次看到 regex d$$-当它后面是一个有效的变量名(什么重要的是名称如下,如即使变量是不确定的只是扩大$PATH$fioejsfoeij或单字符变量,如$-$$,或在结构)${…}$(…)$((…))(也是$[…]在bash 和 zsh,以及 zsh 中的更多构造)。

shell 扩展的完整规则太复杂了,无法在一篇或十几篇文章中描述。在实践中,记住通常的情况就足够了:

  • \ (反斜杠) 引用下一个字符,除非它是换行符,并且反斜杠总是被去除;
  • '…'(单引号)引用除'自身之外的每个字符;
  • "…"(双引号)引用除"$\`, 和\双引号内的每个字符会导致后面的字符按字面意思解释,并且仅在下一个字符是特殊字符时才被剥离。