我们什么时候需要用大括号括住 shell 变量?

问题描述 投票:0回答:7

在shell脚本中,什么时候用

{}
来扩展变量?

例如,我看到了以下内容:

var=10        # Declare variable

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

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

bash shell syntax curly-braces variable-expansion
7个回答
1054
投票

在这个特定的例子中,它没有区别。然而,

{}
中的
${}
是有用的,如果你想扩展字符串中的变量
foo

"${foo}bar"

因为

"$foobar"
会扩展由
foobar
.

标识的变量

在以下情况下也无条件需要花括号:

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

在任何地方都这样做,而不仅仅是在可能有歧义的情况下,可以被认为是良好的编程习惯。这既是为了保持一致性,也是为了避免像

$foo_$bar.jpg
这样的意外,在这种情况下,下划线成为变量名称的一部分在视觉上并不明显。


169
投票

变量声明和赋值时没有

$
{}
。你必须使用

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
并不像你想象的那样!


40
投票

您使用

{}
进行分组。需要大括号来取消引用数组元素。例子:

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

31
投票

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

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

结果:

./folder/subfolder/file.txt ./folder

STRING="This is a string"
echo ${STRING// /_}

结果:

This_is_a_string

你是对的,不需要“常规变量”......但它对调试和阅读脚本更有帮助。


21
投票

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

即使没有歧义范围,也不要过于谨慎并使用

{}
进行 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

参见:


17
投票

变量名的结尾通常用空格或换行符表示。但是,如果我们在打印变量值后不需要空格或换行符怎么办?大括号告诉 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的回答已经说明了这一点,但是他的例子有点太抽象了)


3
投票

根据 SierraX 和 Peter 关于文本操作的建议,大括号

{}
用于将变量传递给命令,例如:

假设您有一个 sposi.txt 文件,其中包含意大利著名小说的第一行:

> sposi="somewhere/myfolder/sposi.txt"
> cat $sposi

输出:

quel ramo del lago di como che volge a mezzogiorno

现在创建两个变量:

# Search the 2nd word found in the file that "sposi" variable points to
> word=$(cat $sposi | cut -d " " -f 2)

# This variable will replace the word
> new_word="filone"

现在将 word 变量内容替换为 sposi.txt 文件中的 new_word 之一

> sed -i "s/${word}/${new_word}/g" $sposi
> cat $sposi

输出:

quel filone del lago di como che volge a mezzogiorno

“ramo”一词已被替换。

© www.soinside.com 2019 - 2024. All rights reserved.