我正在尝试从bash中存储在变量中的一组字符串中提取字符串,例如foo
:
foo="I foobar you"
使用awk
,但当我用单引号和双引号包裹awk
时,我得到了不同的结果:
$ echo $foo | awk '{print $2}'
$ foobar
$ echo $foo | awk "{print $2}"
$ I foobar you
有人可以告诉我为什么'
和"
在包装awk
时会导致不同的结果吗?
答案 0 :(得分:3)
这是因为当使用双引号时,shell会尝试将其作为位置参数或变量展开,然后再将其传递给awk。在您的情况下,它会尝试展开$1
,但没有找到它的值,因此扩展结果为 nothing ,这就是为什么您在awk中打印默认打印操作的原因整条线。
我们单独引用awk命令的原因是我们想要一个普通的字符串,并且在由Awk命令本身处理之前,不会被shell修改/篡改,该命令本身将$1
理解为第一个字段(带有默认空格分隔符)
答案 1 :(得分:1)
根据shell引用规则:
单引号('')保护开始和结束引号之间的所有内容。 shell不对引用的文本进行解释,将其逐字传递给命令。
在你的代码{print $ 2}中传递,因为它是作为动作的awk:
$ echo $foo | awk '{print $2}'
$ foobar
双引号(“”)保护开头报价和收盘价之间的大部分内容。 shell至少对引用的文本执行变量和命令替换。不同的shell可能会对双引号文本执行其他类型的处理。由于双引号文本中的某些字符由shell处理,因此必须在文本中对其进行转义。值得注意的是字符'$',''','\'和'“',如果要将它们传递给程序,则必须在双引号文本中加上反斜杠。
所以你必须逃避$以获得第二列的值为:
$ echo $foo | awk "{print \$2}"
$ foobar
否则awk会按照您的情况执行打印整行的默认操作。
完全同意@Ed Mortan关于引用shell变量的最佳实践。虽然双引号是默认的,但如果不小心......
$ echo "$foo" with double quotes
$ I foobar you
$ echo ‘$foo’ with single quotes
$ $foo
请记住,引用规则特定于shell。以上规则仅适用于POSIX-complaint,Bourne风格的shell(如Bash,GNU Bourne-Again Shell)。它与awk,sed,grep等无关......