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

x0fgdtte  于 2023-10-23  发布在  Shell
关注(0)|答案(7)|浏览(112)

在shell脚本中,我们在扩展变量时什么时候使用{}
例如,我看到以下内容:

var=10        # Declare variable

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

是有很大的不同,还是只是风格不同?一个比另一个更好吗?

bnl4lu3b

bnl4lu3b1#

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

"${foo}bar"

因为"$foobar"将替代地扩展由foobar标识的变量。
在以下情况下,也无条件需要使用大括号:

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

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

ca1c2owp

ca1c2owp2#

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

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

flvtvl50

flvtvl503#

使用{}进行分组。大括号是取消引用数组元素所必需的。范例:

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

5f0d552i4#

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

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

测试结果:

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

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

测试结果:

This_is_a_string

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

pengsaosao

pengsaosao5#

访问数组元素和执行大括号展开总是需要大括号。
最好不要过于谨慎,使用{}来扩展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

请参阅:

omvjsjqw

omvjsjqw6#

变量名的结尾通常用空格或换行符表示。但是,如果我们不想在打印变量值后使用空格或换行符呢?花括号告诉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"

Example 2)Java classpath with versioned jars

# 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的答案已经说明了这一点,但他的例子有点过于抽象)

iszxjhcz

iszxjhcz7#

根据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"

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

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

输出:quel filone del lago di como che volge a mezzogiorno
“ramo”一词已被替换。

相关问题