我有这个简单的代码:
#~/bin/sh
partitions="$(ls -1 /dev/loop?* | tr '\n' ' ')"
for partition in ${partitions}
do
echo "A loop partition: ${partition}"
done
有输出
A loop partition: /dev/loop0
A loop partition: /dev/loop1
A loop partition: /dev/loop2
A loop partition: /dev/loop3
A loop partition: /dev/loop4
A loop partition: /dev/loop5
A loop partition: /dev/loop6
A loop partition: /dev/loop7
A loop partition: /dev/loop-control
当我在${partitions}
循环中的for
变量周围加上引号(使其变为"${partitions}"
)时,输出将变得不同。
带引号:
#~/bin/sh
partitions="$(ls -1 /dev/loop?* | tr '\n' ' ')"
for partition in "${partitions}"
do
echo "A loop partition: ${partition}"
done
新输出:
A loop partition: /dev/loop0 /dev/loop1 /dev/loop2 /dev/loop3 /dev/loop4 /dev/loop5 /dev/loop6 /dev/loop7 /dev/loop-control
为什么报价会以这种方式影响输出?
有人告诉我,将${vars}
放在shell脚本的引号中是一种好习惯。这实际上是不好的做法吗?
答案 0 :(得分:3)
使用引号可防止字符串拆分(将其中包含单词的项目分解为多个片段)和全局扩展(将每个片段视为可能与多个文件名匹配的模式)。
但是,您的原始代码依赖于字符串拆分,因为它会将partitions
存储为单个字符串。请勿这样做:将列表存储在数组变量中,这样即使抑制了字符串拆分也可以保留单独的标识。
shopt -s nullglob # cause a glob with no matches to not generate any items
partitions=( /dev/loop?* ) # generate our list of partitions *as an array*
for partition in "${partitions[@]}"; do # ...then iterate over "${array[@]}"
echo "A loop partition: ${partition}"
done
上面的方法更有效(它仅使用内置在shell本身中的工具,而ls
不是),并且更正确(它不会将文件名用空格分割成单独的单词,也不会替换在存在此类名称时,请使用其他文件名)。
答案 1 :(得分:2)
在变量周围加上引号会使它的值变成单个单词,即使它包含空格也是如此。但是,for
遍历变量中的单词。您已经明确创建了一个变量,并用空格将其分隔开来,然后通过添加引号来关闭单词拆分。