Bash 什么时候外壳变量周围需要大括号?
在shell脚本中,何时在扩展变量时使用Bash 什么时候外壳变量周围需要大括号?,bash,shell,syntax,curly-braces,Bash,Shell,Syntax,Curly Braces,在shell脚本中,何时在扩展变量时使用{} 例如,我看到了以下内容: var=10 # Declare variable echo "${var}" # One use of the variable echo "$var" # Another use of the variable 是有显著的区别,还是仅仅是风格?一个比另一个好吗?在这个特定的例子中,它没有区别。但是,如果要展开字符串中的变量foo,则${}中的{}非常有用 "${foo}bar" 由于“$fooba
{}
例如,我看到了以下内容:
var=10 # Declare variable
echo "${var}" # One use of the variable
echo "$var" # Another use of the variable
是有显著的区别,还是仅仅是风格?一个比另一个好吗?在这个特定的例子中,它没有区别。但是,如果要展开字符串中的变量
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
不会做你可能认为它会做的事情 使用{}
进行分组。大括号是取消引用数组元素所必需的。例如:
dir=(*) # store the contents of the directory into an array
echo "${dir[0]}" # get the first entry.
echo "$dir[0]" # incorrect
您还可以在大括号内执行一些文本操作:
STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}
结果:
./folder/subfolder/file.txt ./folder
This_is_a_string
或
结果:
./folder/subfolder/file.txt ./folder
This_is_a_string
你是对的,在“正则变量”是不需要的。。。但它对调试和读取脚本更有帮助。变量名的结尾通常用空格或换行符表示。但是如果我们在打印变量值后不需要空格或换行符呢?大括号告诉shell解释器变量名的结尾在哪里 经典示例1)-不带尾随空格的shell变量 示例2)带有版本化JAR的Java类路径
(Fred的回答已经说明了这一点,但他的示例有点过于抽象)根据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文件中的新单词替换单词variable content
> sed -i "s/${word}/${new_word}/g" $sposi
> cat $sposi
输出:quel filone del lago di como che volge a mezzogiorno
“ramo”一词已被替换 访问数组元素和执行大括号扩展总是需要大括号 最好不要过于谨慎,使用
{}
进行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
见:
{}
被称为<代码>${}称为变量扩展。他们做不同的事情。除了无扩展位之外,我将向上投票。@NewUser“除了数组之外,它不是真正需要的”不是这样,大括号是脚本中非常有用的构造所必需的。我见过许多sed和awk脚本可以用一些参数扩展来代替。@caffinatedmonkey$()
用于执行命令,这样md5sum=$(md5sum foo.bin)
将md5sum foo.bin
的输出存储在变量md5sum
中,现在可以使用${md5sum}
访问该变量。此外,+1和更多的精神,以OP提到它的良好做法是明确的@L0j1k说到明确性,我发现重要的一点是,$()
从一个@karatedog${1:-20}
是参数扩展的一种形式。这里不明显,因为它主要使用数字和算术运算符,这让我们误以为涉及算术,但它实际上指的是位置参数$1
,如果没有定义,它将被默认值20
(语法是${variable:-default\u value}
)。在变量周围没有大括号的情况下,这同样有效。您可能需要修复这一已知的新的位。尽管如此,我还是无法理解第一行dir=(*)
。据我所知,dir
是一个用于列出目录内容的内置命令(相当于ls-C-b
)。您能解释一下吗?在shell编程中,命令和参数必须用空格隔开。在这里,您可以看到没有空格的等号,这意味着这是一个变量赋值dir
是变量的名称,括号用于将文件名扩展名*
收集到一个数组中。@Jarvis在本例中,dir这个词除了作为接受赋值的变量外没有其他意义。通过使用foo作为变量可以看到这一点<代码>foo=(*);echo“${foo[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