在bash中给出以下代码:
filename=${1}
content1=${@:2}
content2="${@:2}"
content3=${*:2}
content4="${*:2}"
echo "${content1}" > "${filename}"
echo "${content2}" >> "${filename}"
echo "${content3}" >> "${filename}"
echo "${content4}" >> "${filename}"
“内容”之间有什么区别?我何时会看到区别?保存我获得的内容的更好方法是什么?为什么?
答案 0 :(得分:2)
在作业中,除非用空格括起来,否则不必用引号将其括起来,以防止单词分裂和混乱。
这两个是相同的:
myvar=$var
myvar="$var"
但这些不是:
myvar='has space'
myvar=has space
最后一个尝试在环境变量space
设置为值myvar
的情况下运行命令has
。
这意味着content1
与content2
相同,并且content3
与content4
相同,因为它们仅在RHS引用上不同。
差异因此归结为$@
和$*
之间的差异;使用子数组的事实无关紧要。引用手册:
(用于$*
):
在双引号内进行扩展时,它会扩展为一个单词,每个参数的值都由
IFS
特殊变量的第一个字符分隔。
(用于$@
):
在双引号内进行扩展时,每个参数都会扩展为一个单独的单词。
由于您使用的是引号(使用$@
或$*
时几乎总是应该使用引号,所以区别在于"${*:2}"
是单个字符串,由第一个字符分隔IFS
和"${@:2}"
扩展为单独的单词,以空格分隔。
示例:
$ set -- par1 par2 par3 # Set $1, $2, and $3
$ printf '<%s>\n' "${@:2}" # Separate words
<par2>
<par3>
$ printf '<%s>\n' "${*:2}" # Single word, blank separated (default IFS)
<par2 par3>
$ IFS=, # Change IFS
$ printf '<%s>\n' "${*:2}" # Single word, comma separated (new IFS)
<par2,par3>
关于何时使用$@
和$*
:根据经验,您几乎总是想要"$@"
,并且几乎从不< / em>二者之一的无引号版本,因为后者容易分词和修饰。
"$*"
在您希望将数组元素连接到单个字符串中时非常有用,如示例中所示,但是我想,最常见的情况是遍历脚本或函数中的位置参数,这就是{ {1}}是为。另请参见this Bash Pitfall。
答案 1 :(得分:1)
唯一的区别是,使用$*
将导致参数与IFS
的第一个字符连接,而$@
会使参数被单个空格连接(不管IFS
的值如何):
$ set a b c
$ IFS=-
$ c1="$*"
$ c2="$@"
$ echo "$c1"
a-b-c
$ echo "$c2"
a b c
这里的引号不是特别重要,因为赋值右侧的扩展不受单词拆分或路径名扩展的影响; content1
和content2
应该始终相同,content3
和content4
也应该一样。
哪个更好取决于您想要。