为什么 echo 会忽略我的引号字符?

26 shell echo quoting

echo命令不包括我提供的完整文本。例如,如果我这样做:

   $ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '
Run Code Online (Sandbox Code Playgroud)

它输出:

echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk {print } `
Run Code Online (Sandbox Code Playgroud)

'我的 echo 命令中的单引号 ( ) 不包括在内。如果我切换到双引号:

$ echo " echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `  "
Run Code Online (Sandbox Code Playgroud)

echo根本不输出任何东西!为什么在第一个示例中省略了单引号而在第二个示例中不输出任何内容?如何让它准确输出我输入的内容?

Mic*_*zek 35

您的 shell 正在解释引号,包括'",甚至在它们到达echo. 我通常只是在我的论点周围加上双引号来回显,即使它们是不必要的;例如:

$ echo "Hello world"
Hello world
Run Code Online (Sandbox Code Playgroud)

因此,在您的第一个示例中,如果您想在输出中包含文字引号,则需要对它们进行转义:

$ echo \'Hello world\'
'Hello world'
Run Code Online (Sandbox Code Playgroud)

或者它们需要已经在带引号的参数中使用(但它不能是同一种引号,否则无论如何你都需要转义它):

$ echo "'Hello world'"
'Hello world'

$ echo '"Hello world"'
"Hello world"
Run Code Online (Sandbox Code Playgroud)

在第二个示例中,您在字符串中间运行命令替换:

grep  $ARG  /var/tmp/setfile  | awk {print $2}
Run Code Online (Sandbox Code Playgroud)

以 开头的事情$也由 shell 专门处理——它将它们视为变量并用它们的值替换它们。由于很可能这些变量都没有在您的 shell 中设置,因此它实际上只是运行

grep /var/tmp/setfile | awk {print}
Run Code Online (Sandbox Code Playgroud)

由于grep只看到一个参数,它假定该参数是您正在搜索的模式,并且它应该从中读取数据的位置是 stdin,因此它会阻止等待输入。这就是为什么您的第二个命令似乎挂起的原因。

如果您单引号引用参数(这就是您的第一个示例几乎有效的原因),则不会发生这种情况,因此这是获得所需输出的一种方法:

echo \'' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `    '\'
Run Code Online (Sandbox Code Playgroud)

您也可以用双引号引用它,但是您需要转义$s 以便外壳程序不会将它们解析为变量,并且使用反引号以便外壳程序不会立即运行命令替换:

echo "' echo PARAM=\`  grep  \$ARG  /var/tmp/setfile  | awk '{print \$2}' \`    '"
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 7

我不会详细说明为什么您的尝试会如此行事,因为Michael Mrozek 的回答很好地涵盖了这一点。简而言之,单引号 ( '…')之间的所有内容都按字面解释(特别是第一个'标记文字字符串的结尾),而`$之间保留它们的特殊含义"…"

单引号内没有引号,因此您不能将单引号放在单引号字符串中。然而,有一个成语看起来像这样:

echo 'foo'\''bar'
Run Code Online (Sandbox Code Playgroud)

这会打印foo'bar,因为 to 的参数echo由单引号三字符字符串组成foo,与单个字符连接''通过前面的 保护字符不受其特殊含义的影响而获得\),并与单引号三字符字符串连接bar。因此,尽管这不是幕后发生的事情,但您可以将其'\''视为在单引号字符串中包含单引号的一种方法。

如果您想打印复杂的多行字符串,更好的工具是here 文档。一个 here 文档由两个字符组成,<<后跟一个标记,例如<<EOF,然后是一些文本行,然后是该行上的结束标记。如果以任何方式引用标记('EOF'"EOF"\EOF或 'E""OF' 或 ...),则文本按字面解释(就像在单引号内一样,除了 even'是一个普通字符)。如果标记根本没有被引用,那么文本被解释为双引号字符串,并$\`保留它们的特殊状态(但"换行符按字面解释)。

cat <<'EOF'
echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' `
EOF
Run Code Online (Sandbox Code Playgroud)


小智 1

好的,这会起作用:-

echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '
Run Code Online (Sandbox Code Playgroud)

在这里测试它:-

[asmith@yagi ~]$ echo ' echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '\''{print $2}'\'' `    '
 echo PARAM=`  grep  $ARG  /var/tmp/setfile  | awk '{print $2}' ` 
Run Code Online (Sandbox Code Playgroud)