在shell脚本中,当展开变量时,我们什么时候使用{}?

例如,我已经看到以下:

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable

有显著的区别吗,还是只是风格不同?两者孰优孰劣?


当前回答

变量的声明和赋值不带$和{}。你必须使用

var=10

分配。为了从变量中读取(换句话说,“展开”变量),必须使用$。

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

这有时让我感到困惑——在其他语言中,我们以同样的方式引用变量,不管它是在赋值的左边还是右边。但是shell脚本是不同的,$var=10并没有做您可能认为它做的事情!

其他回答

在这个特殊的例子中,没有区别。然而,如果你想在字符串中扩展变量foo, ${}中的{}是有用的

"${foo}bar"

因为“$foobar”将展开由foobar标识的变量。

大括号在以下情况下也是无条件需要的:

展开数组元素,如${array[42]} 使用参数展开操作,如${filename%。*}(删除扩展名) 扩展超过9的位置参数:"$8 $9 ${10}${11}"

在任何地方都这样做,而不是只在可能有歧义的情况下这样做,可以被认为是很好的编程实践。这既是为了一致性,也是为了避免像$foo_$bar.jpg这样的意外,在这种情况下,下划线成为变量名的一部分在视觉上并不明显。

变量的声明和赋值不带$和{}。你必须使用

var=10

分配。为了从变量中读取(换句话说,“展开”变量),必须使用$。

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

这有时让我感到困惑——在其他语言中,我们以同样的方式引用变量,不管它是在赋值的左边还是右边。但是shell脚本是不同的,$var=10并没有做您可能认为它做的事情!

花括号总是用于访问数组元素和执行大括号展开。

不要过于谨慎,使用{}进行shell变量扩展,即使在不存在歧义的情况下也是如此。

例如:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_arch       # {} is needed since _ can be a part of shell variable name

所以,这三行最好写成:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

这绝对更有可读性。

由于变量名不能以数字开头,shell不需要在有编号的变量(如$1,$2等)周围加上{},除非变量展开后跟着一个数字。这太微妙了,它确实使得在这样的上下文中显式地使用{}:

set app      # set $1 to app
fruit=$1le   # sets fruit to apple, but confusing
fruit=${1}le # sets fruit to apple, makes the intention clear

See:

Linux环境变量名中允许使用的字符

变量名的末尾通常用空格或换行符表示。但是如果我们在打印变量值后不需要空格或换行符怎么办?花括号告诉shell解释器变量名的结尾在哪里。

经典示例1)-没有尾随空格的shell变量

TIME=10

# WRONG: no such variable called 'TIMEsecs'
echo "Time taken = $TIMEsecs"

# What we want is $TIME followed by "secs" with no whitespace between the two.
echo "Time taken = ${TIME}secs"

例2)带有版本控制的jar的Java类路径

# WRONG - no such variable LATESTVERSION_src
CLASSPATH=hibernate-$LATESTVERSION_src.zip:hibernate_$LATEST_VERSION.jar

# RIGHT
CLASSPATH=hibernate-${LATESTVERSION}_src.zip:hibernate_$LATEST_VERSION.jar

(Fred的回答已经说明了这一点,但他的例子有点太抽象了)

使用{}进行分组。对数组元素进行解引用时需要使用大括号。例子:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect