我有以下示例:
$ a="$(ls)"
$ echo $a
backups cache crash lib local lock log mail opt run snap spool tmp
$
$ echo "$a"
backups
cache
crash
lib
local
lock
log
mail
opt
run
snap
spool
tmp
现在printf
:
$ printf $a
backups
$
$ printf "$a"
backups
cache
crash
lib
local
lock
log
mail
opt
run
snap
spool
tmp
为什么输出如此不同?在这种情况下,报价有什么作用?有人可以解释一下这是怎么回事吗?
PS 找到了有关该行为的一些解释ls
:
ls 的输出有换行符,但显示在一行上。为什么?
https://superuser.com/questions/424246/what-is-the-magic-separator- Between-filenames-in-ls-output
http://mywiki.wooledge.org/ParsingLs
可以这样检查换行符:
ls | od -c
答案1
echo $a
是相同的
echo backups cache crash lib local lock log mail opt run snap spool tmp
而echo "$a"
与相同
echo 'backups
cache
crash
lib
local
lock
log
mail
opt
run
snap
spool
tmp'
看https://mywiki.wooledge.org/Quotes。
第一个参数printf
是格式化字符串,与printf $a
它相同,因此printf backups cache crash lib local lock log mail opt run snap spool tmp
它使用该字符串backups
作为格式并丢弃其余部分,因为格式化字符串中没有任何东西%s
可以使用它们。就像:
$ printf foo whatever
foo$
$ printf '%s\n' foo whatever
foo
whatever
不要a="$(ls)"
尝试创建一个保存文件名的标量变量,因为它很脆弱,而是将a=(*)
它们保存在数组中。
答案2
感谢@Ed Morton 和@Kusalananda 的解释。
我想我的问题是我一直认为默认情况下ls
使用空格或制表符分割文件。但事实上,事实证明,它用换行符分隔它们,但在打印到终端时按列输出文件(垂直排序)。可以通过以下方式检查换行符:
ls | od -c
我会将 @Kusalananda 的答案从评论部分移至答案,因为它很有帮助:
简而言之,echo
输出其参数,参数之间有空格。这就是作用echo
。
使用时echo $a
,shell$a
根据空格、制表符和换行符将 的内容拆分为多个参数(然后还在每个生成的单词上进行文件名通配)。echo
然后打印它们,它们之间有空格。
使用 时echo "$a"
,您只需给 echo 一个参数。该字符串"$a"
包含来自 输出的换行符ls
,这些换行符由 保留并输出echo
。