当您执行以下操作时:
echo 'Hello World'
或像这样:
x=12345
echo "x is: $x"
在第一个示例中,该echo
命令会接收'Hello World'
还是会接收Hello World
?
在第二个示例中,该echo
命令接收"x is: $x"
还是接收x is: 12345
?
所以基本上我的问题是:单引号和双引号是由bash
还是由处理echo
?
bash处理引号,变量扩展,通配符以及bash手册中有关扩展的所有其他内容。
例如,当您运行bash命令时echo "x is: $x"
,bash对此进行解析以发现它需要echo
使用一个参数()运行该命令x is: 12345
。给定echo "x is" "$x"
,bashecho
使用两个参数运行:x is
和12345
-这就是为什么引号内的两个空格得以保留(它们是参数的一部分,该参数回显了未修改的内容),但引号外的两个空格却未被保留(对于shell,两个用于分隔参数的空格与单个空格一样好,并且echo
总是在它们之间打印单个空格)。
该echo
命令(或任何其他命令)无法知道哪个shell命令产生了该参数x is: 12345
,或者实际上是否知道是否涉及任何shell。以下是产生此参数的一些示例命令:
echo "x is: 12345"
echo 'x is: 12345'
echo x\ is:\ 12345
echo "x is: $x"
echo 'x is:'\ "$x"
echo "$(echo "x ")is: $x"
# Assume there is no other file whose name begins with x in the current directory
touch "x is: $x"; echo x*
也可以exec "echo", "x is: 12345"
在Perl或execlp("echo", "echo", "x is: 12345")
C中,等等。
这适用于每个命令。对于其他壳,尽管它们每个都有一组稍微不同(或明显不同)的扩展集,但同样的原理也适用。
另一方面,选项由命令处理。例如,ls -l -t
与ls -l "-t"
在bash(或任何类似的壳)都运行ls
在完全相同的方式,用两个参数-l
和-t
。这就是为什么如果您想运行ls
以显示有关名为的文件的信息,没有任何形式的Shell引用都无法帮助您的原因-t
。您可以使用进行操作ls -l -- -t
,即--
作为参数传递。这是大多数命令遵循的约定:后面的任何内容都不--
作为选项进行解析。再次,这是命令的功能;对于外壳,前导破折号没什么特别的。
反斜杠是一件很棘手的事情。在bash和其他shell中,任何引号外的反斜杠表示下一个字符失去其特殊含义。例如,echo \"x\ is:\ 12345\"
prints "x is: 12345"
,因为每个以反斜杠开头的字符都失去了特殊的含义(引号的语法"
,空格的单词分隔符)。但是某些命令也会解释反斜杠。当它们出现时,您需要确保反斜杠到达了它们。例如,在bash中,该echo
命令默认情况下会按字面意义显示反斜杠,但是如果您通过该选项-e
或shopt xpg_echo
先运行,则echo
会有其自己的转义序列(对于bash,echo
在不同的Shell中和在不同的系统上的命令对于它们是否特别对待反斜杠有不同的规则)。例如,echo 'a\nb'
打印a\nb
,同时echo -e 'a\nb'
打印a
-newline-b
因为\n
手段“换行”来echo -e
。另一方面,由于外壳将其展开,因此这里的echo a\nb
打印内容是“引用下一个字符”。anb
\n
\
另外,当涉及多个外壳(例如,SSH)时,请务必小心。当您ssh
在外壳程序中运行时,本地外壳程序将照常解析命令。SSH客户端在其非选项参数之间添加空格,并将结果字符串发送到SSH服务器。SSH服务器将此字符串传递到远程Shell。这意味着在您在终端或shell脚本中键入的内容与在远程计算机上执行的内容之间有两轮完整的Shell扩展。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句