该echo
命令不包括我提供的完整文本。例如,如果我这样做:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
它输出:
echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } `
我的 echo 命令中的单引号 ( '
) 不包括在内。如果我切换到双引号:
$ echo " echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` "
echo
根本不输出任何东西!为什么它在第一个示例中省略单引号,而在第二个示例中不输出任何内容?如何让它准确输出我输入的内容?
答案1
您的 shell 正在解释引号,包括'
和"
,甚至在它们到达 之前echo
。我通常只是在我的论点周围加上双引号以回应,即使它们是不必要的;例如:
$ echo "Hello world"
Hello world
因此,在第一个示例中,如果您想在输出中包含文字引号,则需要转义它们:
$ echo \'Hello world\'
'Hello world'
或者它们已经需要在带引号的参数中使用(但不能是同一种引号,否则您无论如何都需要转义它):
$ echo "'Hello world'"
'Hello world'
$ echo '"Hello world"'
"Hello world"
在第二个示例中,您在字符串中间运行命令替换:
grep $ARG /var/tmp/setfile | awk {print $2}
以 开头的内容$
也由 shell 专门处理——它将它们视为变量并用它们的值替换它们。由于很可能这些变量都没有在您的 shell 中设置,因此它实际上只是运行
grep /var/tmp/setfile | awk {print}
由于grep
只看到一个参数,它假设该参数是您正在搜索的模式,并且它应该从中读取数据的位置是 stdin,因此它会阻止等待输入。这就是为什么你的第二个命令似乎挂起。
如果您单引号参数,则不会发生这种情况(这就是您的第一个示例几乎成功的原因),因此这是获得所需输出的一种方法:
echo \'' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '\'
您也可以用双引号将其引起来,但是您需要转义 s,$
以便 shell 不会将它们解析为变量,并且需要转义反引号,以便 shell 不会立即运行命令替换:
echo "' echo PARAM=\` grep \$ARG /var/tmp/setfile | awk '{print \$2}' \` '"
答案2
我不会详细说明为什么您的尝试会这样做,因为迈克尔·莫罗泽克的回答很好地涵盖了这一点。简而言之,单引号 ( '…'
) 之间的所有内容均按字面解释(特别是第一个'
标记文字字符串的结尾),而`
和$
之间保留其特殊含义"…"
。
单引号内没有引号,因此不能将单引号放在单引号字符串内。然而,有一个习语看起来像这样:
echo 'foo'\''bar'
这会打印foo'bar
,因为 的参数echo
由单引号三字符字符串 组成foo
,与单个字符(通过前面的'
保护字符免受其特殊含义获得)连接,并与单引号三字符字符串 串联。因此,尽管这并不完全是幕后发生的事情,但您可以将其视为在单引号字符串中包含单引号的一种方法。'
\
bar
'\''
如果你想打印复杂的多行字符串,更好的工具是这里的文档。此处文档由两个字符组成<<
,后跟一个标记(例如 )<<EOF
,然后是一些文本行,最后是该行上单独的结束标记。如果以任何方式引用标记('EOF'
或"EOF"
或\EOF
或'E""OF'或...),则文本将按字面解释(就像在单引号内一样,除了even'
是普通字符)。如果标记根本没有被引用,那么文本将像双引号字符串一样被解释,并$\`
保留其特殊状态(但"
换行符按字面解释)。
cat <<'EOF'
echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' `
EOF
答案3
好的,这会起作用:-
echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '\''{print $2}'\'' ` '
在这里测试它:-
[asmith@yagi ~]$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '\''{print $2}'\'' ` '
echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' `
答案4
让我们听从您的命令
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
首先将其分割成单词,使用不带引号的空格作为分隔符:
Arg[1]=“' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print”
Arg[2]=“$2}' ` '”
接下来,我们进行参数扩展:扩展$…
但不在内部'…'
。由于$2
是空的(除非您通过eg设置它set -- …
),它将被替换为空字符串。
Arg[1]=“' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print”
Arg[2]=“}' ` '”
接下来,删除引号。
Arg[1]=“ echo PARAM=` grep $ARG /var/tmp/setfile | awk {print”
Arg[2]=“} ` ”
然后这些参数被传递给 echo,它将逐个打印它们,并用一个空格分隔。
“ echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } ` ”
我希望这个分步说明能够使观察到的行为更加清晰。为了避免这个问题,请像这样转义单引号:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '\''{print $2}'\'' ` '
这将结束单引号字符串,然后向单词添加(转义的)单引号,然后开始一个新的单引号字符串,所有这些都不会将单词分开。