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)
为什么会这样?规则是什么?
引号由外壳展开,它们决定了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 扩展的完整规则太复杂了,无法在一篇或十几篇文章中描述。在实践中,记住通常的情况就足够了:
\
(反斜杠) 引用下一个字符,除非它是换行符,并且反斜杠总是被去除;'…'
(单引号)引用除'
自身之外的每个字符;"…"
(双引号)引用除"$\`
, 和\
双引号内的每个字符会导致后面的字符按字面意思解释,并且仅在下一个字符是特殊字符时才被剥离。