考虑两个壳样本
$ ls
myDoc.html
SomeDirectory
someDoc.txt
Run Code Online (Sandbox Code Playgroud)
和
$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt
Run Code Online (Sandbox Code Playgroud)
第一个执行ls,据我所知,将当前工作目录的内容附加到stdout文件中(这是终端显示的内容)。这样对吗?
第二个获取ls命令的值(这意味着是当前工作目录的内容)并将其打印到stdout文件中。这样对吗?
为什么这两个命令给出不同的输出?
Joh*_*024 76
当您运行此命令时:
ls
Run Code Online (Sandbox Code Playgroud)
终端显示ls.
当您运行此命令时:
echo $(ls)
Run Code Online (Sandbox Code Playgroud)
shell 捕获输出$(ls)并对其进行分词。默认情况下IFS,这意味着所有空格序列(包括换行符)都被单个空格替换。这就是为什么输出echo $(ls)出现在一行上。
有关分词的高级讨论,请参阅Greg 的常见问题解答。
Shell 不会对引号中的字符串执行分词。因此,您可以通过以下方式抑制分词并保留多行输出:
echo "$(ls)"
Run Code Online (Sandbox Code Playgroud)
ls 和多行输出您可能已经注意到,ls有时每行打印多个文件:
$ ls
file1 file2 file3 file4 file5 file6
Run Code Online (Sandbox Code Playgroud)
这是输出ls到终端时的默认设置。当输出不直接进入终端时,ls将其默认值更改为每行一个文件:
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
Run Code Online (Sandbox Code Playgroud)
此行为记录在man ls.
$(...)是命令替换,shell 从命令替换的输出中删除尾随的换行符。这通常不会引起注意,因为默认情况下echo会在其输出的末尾添加一个换行符。所以,如果你从末失去一个换行符$(...),并且获得一个距离echo,没有任何改变。但是,如果您的命令的输出以2 个或更多换行符结尾,而echo只添加一个,则您的输出将缺少一个或多个换行符。例如,我们可以使用printf生成尾随换行符。请注意,尽管换行数不同,以下两个命令都会产生一个空行的相同输出:
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
Run Code Online (Sandbox Code Playgroud)
此行为记录在man bash.
让我们创建三个文件:
$ touch 'file?' file1 file2
Run Code Online (Sandbox Code Playgroud)
观察之间的差异ls file?和echo $(ls file?):
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
Run Code Online (Sandbox Code Playgroud)
在 的情况下echo $(ls file?),文件 globfile?被扩展了两次,导致文件名file1和file2在输出中出现两次。这是因为,正如 Jeffiekins 指出的那样,shell 在运行之前首先执行路径名扩展ls,然后在echo运行之前再次执行。
如果我们使用双引号,可以抑制第二个路径名扩展:
$ echo "$(ls file?)"
file?
file1
file2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
58222 次 |
| 最近记录: |