我可以看到 GNU Grep 中的某些模式可以括在括号内,而某些其他模式则不需要。例如,仅当单词包含在引号内时,匹配单词的开头才有效。
user@host:~/Desktop$ grep -E '\<H' test
Hello World
user@host:~/Desktop$ grep -E \<H test
[测试包含字符串 Hello World]
但是匹配文件的结尾和开头不需要美元:
user@host:~/Desktop$ egrep d$ test
Hello World
为什么会这样呢?规则是什么?
答案1
引号由 shell 扩展,它们决定所grep
看到的内容。
对于grep -E '\<H'
,单引号之间的字符按字面意思传递,因此 grep 会看到\<H
包含单词开头锚点的正则表达式\<
。
使用 时,反斜杠字符会删除shell 中grep -E \<H
的特殊含义,并看到正则表达式。您会看到像这样的行的匹配项。<
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
or$fioejsfoeij
或单字符变量,如$-
or $$
),或在结构${…}
, $(…)
, $((…))
(也可以$[…]
在bash 和 zsh,以及 zsh 中的更多构造)。
shell 扩展的完整规则太复杂,无法用一篇或十几篇文章来描述。在实践中,记住通常的情况就足够了:
\
(反斜杠)引用下一个字符,除非它是换行符,并且反斜杠始终被删除;'…'
(单引号)引用除'
自身之外的每个字符;"…"
(双引号)引用除 之外的每个字符"$\`
,并且\
在双引号内会导致后面的字符按字面解释,并且仅在下一个字符特殊时才被删除。
答案2
首先\<
由 shell 转义,其值成为文字<
字符。所以传递给的正则表达式grep
是 string <H
,它没有特殊的含义。
如果您需要深入了解这种特定关系,您应该查阅吉尔斯的答案。