我们什么时候需要围绕shell变量的花括号?

New*_*ser 602 syntax bash shell curly-braces

在shell脚本中,我们{}何时在扩展变量时使用?

例如,我见过以下内容:

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable
Run Code Online (Sandbox Code Playgroud)

是否存在显着差异,还是只是风格?一个比另一个更受欢迎吗?

Fre*_*Foo 691

在这个特定的例子中,它没有任何区别.但是,如果要在字符串中展开变量,则{}in ${}非常有用foo

"${foo}bar"
Run Code Online (Sandbox Code Playgroud)

因为"$foobar"会改为扩大foobar.

在以下情况下无条件地需要使用花括号:

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

在任何地方这样做,而不仅仅是在可能模糊的情况下,可以被认为是良好的编程实践.这既是为了保持一致性,也是为了避免出现意外情况,例如$foo_$bar.jpg,下划线成为变量名称的一部分在视觉上并不明显.

  • `{}`被称为[大括号扩展](http://ss64.com/bash/syntax-expand.html).`$ {}`被称为变量扩展.他们做不同的事情.除了没有扩展位之外,我还要投票给你. (99认同)
  • 说到显性,我发现重要的是要提到`$()`从[subshel​​l]执行命令(http://www.tldp.org/LDP/abs/html/subshel​​ls.html#SUBSHELLSREF). (10认同)
  • @caffinatedmonkey` $()`用于执行命令,这样`md5sum = $(md5sum foo.bin)`将`md5sum foo.bin`的输出存储在变量`md5sum`中,现在可以使用`$访问{的md5sum}`.此外,为了提及明确的良好做法,在OP的精神上+1和更多! (9认同)
  • @NewUser"*所以除了数组之外并不是真的需要*"不是这样,[PARAMETER EXPANSION](http://wiki.bash-hackers.org/syntax/pe)需要大括号,这是一个非常有用的结构.脚本.我见过很多sed和awk脚本,可以用一些参数扩展来代替. (5认同)
  • @karatedog `${1:-20}` 是参数扩展的一种形式。这里不明显,因为它主要使用数字和算术运算符,让我们误以为涉及算术,但它实际上指的是位置参数“$1”,如果未定义它将被默认值“20”替换(语法是`${variable:-default_value}`)。 (5认同)
  • 那么`$()`呢? (3认同)

Aar*_*aid 119

变量的声明,并没有分配$,没有{}.你必须使用

var=10
Run Code Online (Sandbox Code Playgroud)

分派.为了从变量中读取(换句话说,'展开'变量),必须使用$.

$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.
Run Code Online (Sandbox Code Playgroud)

这有时让我困惑 - 在其他语言中,我们以相同的方式引用变量,无论它是在赋值的左侧还是右侧.但是shell脚本是不同的,$var=10不会做你认为它做的事情!


gle*_*man 30

{}用于分组.大括号需要取消引用数组元素.例:

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

  • 在 shell 编程中,命令和参数必须用空格相互分隔。在这里,您会看到没有空格的等号,这意味着这是一个变量赋值。`dir` 是变量的名称,括号用于将文件名扩展 `*` 收集到一个数组中。 (4认同)

小智 26

您还可以在大括号内进行一些文本操作:

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}
Run Code Online (Sandbox Code Playgroud)

结果:

./folder/subfolder/file.txt ./folder
Run Code Online (Sandbox Code Playgroud)

要么

STRING="This is a string"
echo ${STRING// /_}
Run Code Online (Sandbox Code Playgroud)

结果:

This_is_a_string
Run Code Online (Sandbox Code Playgroud)

你是正确的"常规变量"是不需要的...但它对调试和阅读脚本更有帮助.


cod*_*ter 12

访问数组元素和执行大括号扩展总是需要大括号。

{}即使没有歧义,也不要过度谨慎并用于 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
Run Code Online (Sandbox Code Playgroud)

因此,最好将三行写为:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path
Run Code Online (Sandbox Code Playgroud)

这绝对更具可读性。

由于变量名称不能以数字开头,壳不需要{}围绕编号的变量(如$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
Run Code Online (Sandbox Code Playgroud)

看:

  • 我不同意“不过度谨慎就好”的说法;过度谨慎绝对是更好的选择。我宁愿有一百万个不必要的大括号,也不愿出现一个破坏某些东西的错误,特别是考虑到在 shell 脚本中找到错误(无用的错误消息,或者根本没有错误)是多么困难。 (13认同)
  • “不要过于谨慎是件好事”:我想知道大多数人是怎么想的。始终使用大括号,这样您就不会在需要时忘记它们,或者仅在需要时使用它们,以提高可读性。 (4认同)
  • 我认为正是缺乏意识导致程序员在不需要的时候使用花句。这种无知与另一个常见错误类似,即不使用双引号来防止无意的分词或通配符。从根本上来说,现实是程序员并不像 Python 和 Ruby 等其他脚本语言那样认真对待 shell 脚本。 (2认同)
  • 诚然。我最讨厌的是,每个人似乎都认为 shell 脚本中的所有变量都应该全部大写:) (2认同)

Sri*_*bat 11

变量名称的结尾通常用空格或换行符表示.但是如果我们在打印变量值后不想要空格或换行符怎么办?花括号告诉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"
Run Code Online (Sandbox Code Playgroud)

示例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
Run Code Online (Sandbox Code Playgroud)

(弗雷德的回答已经说明了这一点,但他的例子有点过于抽象)