Answers:
“日期”将仅扩展到date
命令的输出。但是,它将在输出中有多个连续的空格字符的地方删除多余的空格字符。(这是因为命令替换会受到单词拆分的影响,并且因为echo
命令如何处理多个参数。)
在“`date`”中,双引号是弱引号,因此它们将扩展变量(尝试“ $ PWD”)并执行命令替换。扩展结果作为单个参数传递给echo
命令,其中包括任何连续的空格:即,不执行单词拆分。
在'date'中,单引号是更强的引号,因此它们将不允许扩展变量或在其中进行命令替换。
请参阅此链接以获取更多说明。
编辑了迈克尔·塞尔曼(Michael Suelmann)在以下评论中正确指出的第一点。
date
命令相同的内容。
都
echo `date`
和
echo "`date`"
将显示日期。后者的输出看起来像是date
自己运行的输出。
但是有一个区别:用"
引号"
引起来的引号将echo
作为单个参数发送到。引号将整个命令的输出封装为一个参数。因为echo
只是按顺序打印出其参数,并且之间有空格,所以它基本上看起来是相同的。
这是一个细微差别的示例:
echo `date`
产生:
Fri Nov 1 01:48:45 EST 2013
但:
echo "`date`"
产生:
Fri Nov 1 01:48:49 EST 2013
请注意,后面的两个空格Nov
减少为一个不带引号的空格。这是因为shell正在解析每个以空格分隔的元素,并将结果作为6个参数发送给echo。当您引用它时,echo会收到一个参数,并且引号保留空格。
这在echo以外的命令中变得更加重要。例如,想象一个命令foo
需要两个参数:日期和电子邮件地址。
这将在这种情况下起作用:
foo "`date`" joeuser@example.com
但这会通过发送7个参数来混淆脚本:
foo `date` joeuser@example.com
在POSIX shell中,`date`
是命令替换的古老形式。现代语法是$(date)
。
在两种情况下,它们都扩展为 date
并去除尾随的换行符(前提是输出不包含NUL字符)。
但是,如果不在双引号中和列表上下文中(例如,在像echo
您这样的简单命令的参数中),则该扩展还受以下条件的限制:
单词拆分:即根据变量的当前值(默认情况下包含空格,制表符和换行符(以及NUL带有))将“拆分后的换行符的输出date
”拆分成几个单词。$IFS
zsh
例如,如果date
输出Fri 1 Nov 14:11:15 GMT 2013\n
(如经常在英语语言环境,并在内地英国时区所做的),和$IFS
目前包含:
,将被分成3个字:Fri 1 Nov 14
,11
和15 GMT 2013
。
zsh
):是,从上面的分裂所产生的每个字找通配符(*
,?
,[...]
虽然有些炮弹有更多的),并扩大到匹配模式,文件名列表。例如,如果输出date
是?%? 33 */*/* UVC 3432
(像它往往是在金星的语言环境和UVC时区),并且$IFS
是默认值),那么膨胀到所有非隐藏的3个字符的文件名在当前目录中中间性格%
,33
,当前目录的所有非隐藏子目录的所有非隐藏子目录中的所有非隐藏文件,UVC
以及3432
。这就是为什么:
$IFS
其为要拆分的字符。set +f
来禁用它。单引号引用所有内容,因此会使反引号字符按字面意义使用。
示例(使用-x
可以更轻松地查看正在发生的事情):
$ bash --norc -x
bash-4.2$ IFS=:
+ IFS=:
bash-4.2$ echo `date`
++ date
+ echo 'Fri 1 Nov 14' 42 '33 GMT 2013'
Fri 1 Nov 14 42 33 GMT 2013
bash-4.2$ echo "`date`"
++ date
+ echo 'Fri 1 Nov 14:42:41 GMT 2013'
Fri 1 Nov 14:42:41 GMT 2013
bash-4.2$ cd /lib/modules
+ cd /lib/modules
bash-4.2$ export TZ=UVC LC_ALL=vs_VS
+ export TZ=UVC LC_ALL=vs_VS
+ TZ=UVC
+ LC_ALL=vs_VS
bash-4.2$ unset -v IFS # get the default behaviour
+ unset -v IFS
bash-4.2$ echo `date`
++ date
+ echo '?%?' 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
?%? 33 3.10-2-amd64/build/arch 3.10-2-amd64/build/include 3.10-2-amd64/build/Makefile 3.10-2-amd64/build/Module.symvers 3.10-2-amd64/build/scripts 3.10-2-amd64/kernel/arch 3.10-2-amd64/kernel/crypto 3.10-2-amd64/kernel/drivers 3.10-2-amd64/kernel/fs 3.10-2-amd64/kernel/lib 3.10-2-amd64/kernel/mm 3.10-2-amd64/kernel/net 3.10-2-amd64/kernel/sound 3.10-2-amd64/source/arch 3.10-2-amd64/source/include 3.10-2-amd64/source/Makefile 3.10-2-amd64/source/scripts 3.10-2-amd64/updates/dkms 3.10-3-amd64/build/arch 3.10-3-amd64/build/include 3.10-3-amd64/build/Makefile 3.10-3-amd64/build/Module.symvers 3.10-3-amd64/build/scripts 3.10-3-amd64/kernel/arch 3.10-3-amd64/kernel/crypto 3.10-3-amd64/kernel/drivers 3.10-3-amd64/kernel/fs 3.10-3-amd64/kernel/lib 3.10-3-amd64/kernel/mm 3.10-3-amd64/kernel/net 3.10-3-amd64/kernel/sound 3.10-3-amd64/source/arch 3.10-3-amd64/source/include 3.10-3-amd64/source/Makefile 3.10-3-amd64/source/scripts 3.10-3-amd64/updates/dkms UVC 3432
bash-4.2$ echo "`date`"
++ date
+ echo '?%? 33 */*/* UVC 3432'
?%? 33 */*/* UVC 3432
如果输出包含NUL字符,则外壳的行为各不相同:有的将其删除,有的在第一个NUL字符处截断了输出,zsh
保留了它们,但请注意,无论如何外部命令都不能接受包含NUL的参数
使用`date`,您可以将日期输出拆分成多个单词,因为单词拆分是在命令替换后完成的。
使用“`date`”,由于双引号之间有命令替换,因此您将date的输出作为一个单词/参数获得,但是该输出未进一步解析。在下面的示例中,变量扩展如“ $ i”同样有效。
使用“`日期”,您会得到一个字面的“日期”,因为单引号之间没有命令替换。
也许这三种形式的差异将以这种方式更加明显:
> for i in `date`; do echo "$i"; done
Fr
1.
Nov
12:25:30
CET
2013
> for i in "`date`"; do echo "$i"; done
Fr 1. Nov 12:25:38 CET 2013
> for i in '`date`'; do echo "$i"; done
`date`