我在放入转义模式时遇到问题grep
。
我的测试文件是:
export_cc = ${dir}/aaa/bbb/ccc
export_cc = ${dir}/aaa/bbb/eee
export_cc = ${dir}/aaa/bbb/ddd
export_cc = ${dir}/aaa/bbb/fff
export_cc = ${dir}/aaa/bbb/ggg
如果我运行:
~/programming/sandbox $ printf %q 'export_cc = ${dir}/aaa/bbb/ccc'
export_cc\ =\ \$\{dir\}/aaa/bbb/ccc
然后将输出复制到 grep 作为我得到的模式:
~/programming/sandbox $ grep export_cc\ =\ \$\{dir\}/aaa/bbb/ccc file
export_cc = ${dir}/aaa/bbb/ccc
但是如果我将模式放入变量或反引号中,我会得到:
~/programming/sandbox $ grep `printf %q 'export_cc = ${dir}/aaa/bbb/ccc'` file
grep: Trailing backslash
有人能告诉我为什么这会产生差异以及如何在变量中使用带引号的字符串作为grep
模式吗?
答案1
问题是外壳逃逸。\
是 shell 中的特殊字符,也是grep
.
在:
grep export_cc\ =\ \$\{dir\}/aaa/bbb/ccc file
export_cc\ =\ \$\{dir\}/aaa/bbb/ccc
export_cc = ${dir}/aaa/bbb/ccc
在传递给 之前被 shell 解释为一个字符串grep
。您可以使用斯特雷斯去检查:
$ strace grep export_cc\ =\ \$\{dir\}/aaa/bbb/ccc file
execve("/bin/grep", ["grep", "export_cc = ${dir}/aaa/bbb/ccc",...
和命令替换:
grep `printf %q 'export_cc = ${dir}/aaa/bbb/ccc'` file
如果没有双引号,则结果为命令替换曾是拆分和通配符由外壳分为三部分:export_cc\
、=\
、 和\$\{dir\}/aaa/bbb/ccc
。 shell 将它们视为三个字符串,转义所有反斜杠并将它们传递给grep
as export_cc\\
, =\\
, \\$\\{dir\\}/aaa/bbb/ccc
:
$ strace grep $(printf %q 'export_cc = ${dir}/aaa/bbb/ccc') file
execve("/bin/grep", ["grep", "export_cc\\", "=\\", "\\$\\{dir\\}/aaa/bbb/ccc",...
grep
收到一个带有一个反斜杠,export_cc\
后面什么都没有的模式,它显示了消息Trailing backslash
。
为了让它发挥作用,你需要双引号命令替换,并使用打印函数用%s
而不是%q
:
$ grep "$(printf %s 'export_cc = ${dir}/aaa/bbb/ccc')" file
export_cc = ${dir}/aaa/bbb/ccc