在这些情况下,$ {@:2}和$ {*:2}有什么区别?

时间:2018-07-04 17:50:24

标签: bash variable-expansion

在bash中给出以下代码:

filename=${1} 
content1=${@:2}
content2="${@:2}"
content3=${*:2}
content4="${*:2}"
echo  "${content1}" > "${filename}"
echo   "${content2}" >> "${filename}"
echo  "${content3}" >> "${filename}"
echo   "${content4}" >> "${filename}"

“内容”之间有什么区别?我何时会看到区别?保存我获得的内容的更好方法是什么?为什么?

2 个答案:

答案 0 :(得分:2)

在作业中,除非用空格括起来,否则不必用引号将其括起来,以防止单词分裂和混乱。

这两个是相同的:

myvar=$var
myvar="$var"

但这些不是:

myvar='has space'
myvar=has space

最后一个尝试在环境变量space设置为值myvar的情况下运行命令has

这意味着content1content2相同,并且content3content4相同,因为它们仅在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

这里的引号不是特别重要,因为赋值右侧的扩展不受单词拆分或路径名扩展的影响; content1content2应该始终相同,content3content4也应该一样。

哪个更好取决于您想要