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

发布于 2024-12-25 12:34:57 字数 251 浏览 1 评论 0原文

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

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

var=10        # Declare variable

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

是否存在显着差异,或者只是风格?其中一个比另一个更受青睐吗?

In shell scripts, when do we use {} when expanding variables?

For example, I have seen the following:

var=10        # Declare variable

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

Is there a significant difference, or is it just style? Is one preferred over the other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

三生一梦 2025-01-01 12:34:57

在这个特定的例子中,这没有什么区别。 中的 {} 非常有用

"${foo}bar"

但是,如果您想扩展字符串中的变量 foo ,因为 "$foobar " 将扩展由 foobar 标识的变量。

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

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

在任何地方都执行此操作,而不仅仅是在可能不明确的情况下,可以 被考虑良好的编程习惯。这既是为了保持一致性,也是为了避免像 $foo_$bar.jpg 这样的意外情况,下划线成为变量名称的一部分在视觉上并不明显。

In this particular example, it makes no difference. However, the {} in ${} are useful if you want to expand the variable foo in the string

"${foo}bar"

since "$foobar" would instead expand the variable identified by foobar.

Curly braces are also unconditionally required when:

  • expanding array elements, as in ${array[42]}
  • using parameter expansion operations, as in ${filename%.*} (remove extension; strips smallest match)
  • expanding positional parameters beyond 9: "$8 $9 ${10} ${11}"

Doing this everywhere, instead of just in potentially ambiguous cases, can be considered good programming practice. This is both for consistency and to avoid surprises like $foo_$bar.jpg, where it's not visually obvious that the underscore becomes part of the variable name.

不念旧人 2025-01-01 12:34:57

变量的声明和赋值无需 ${}。您必须使用

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

Variables are declared and assigned without $ and without {}. You have to use

var=10

to assign.

In order to read from the variable (in other words, expand the variable), you must use $.

$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.

This has confused me sometimes: in other languages we refer to the variable in the same way, regardless of whether it's on the left or right of an assignment. But shell-scripting is different, $var=10 doesn't do what you might think it does!

伴随着你 2025-01-01 12:34:57

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

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

You use {} for grouping. The braces are required to dereference array elements. Example:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect
浅笑依然 2025-01-01 12:34:57

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

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

Result:

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

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

Result:

This_is_a_string

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

You are also able to do some text manipulation inside the braces:

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

Result:

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

or

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

Result:

This_is_a_string

You are right in "regular variables" are not needed... But it is more helpful for the debugging and to read a script.

那些过往 2025-01-01 12:34:57

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

即使没有歧义的范围,最好不要过于谨慎,并使用 {} 进行 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

请参阅:

Curly braces are always needed for accessing array elements and carrying out brace expansion.

It's good to be not over-cautious and use {} for shell variable expansion even when there is no scope for ambiguity.

For example:

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

So, it is better to write the three lines as:

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

which is definitely more readable.

Since a variable name can't start with a digit, shell doesn't need {} around numbered variables (like $1, $2 etc.) unless such expansion is followed by a digit. That's too subtle and it does make to explicitly use {} in such contexts:

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:

╰ゝ天使的微笑 2025-01-01 12:34:57

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

The end of the variable name is usually signified by a space or newline. But what if we don't want a space or newline after printing the variable value? The curly braces tell the shell interpreter where the end of the variable name is.

Classic Example 1) - shell variable without trailing whitespace

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's answer already states this but his example is a bit too abstract)

就像说晚安 2025-01-01 12:34:57

按照 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”已被替换。

Following SierraX and Peter's suggestion about text manipulation, curly brackets {} are used to pass a variable to a command, for instance:

Let's say you have a sposi.txt file containing the first line of a well-known Italian novel:

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

Ouput: quel ramo del lago di como che volge a mezzogiorno

Now create two variables:

# 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"

Now substitute the word variable content with the one of new_word, inside sposi.txt file

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

Ouput: quel filone del lago di como che volge a mezzogiorno

The word "ramo" has been replaced.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文