When do we need curly braces around shell variables?
在shell脚本中,扩展变量时何时使用
例如,我看到了以下内容:
1 2 3 4 | var=10 # Declare variable echo"${var}" # One use of the variable echo"$var" # Another use of the variable |
是有显著的区别,还是只是风格?一个比另一个更受欢迎吗?
在这个特定的例子中,它没有任何区别。但是,如果要扩展字符串中的变量
1 | "${foo}bar" |
由于
在下列情况下,也无条件地需要大括号:
- 扩展数组元素,如
${array[42]} 。 - 使用参数扩展操作,如
${filename%.*} (删除扩展) - 将位置参数扩展到9以外:
"$8 $9 ${10} ${11}" 。
在任何地方都这样做,而不仅仅是在可能不明确的情况下,可以被视为良好的编程实践。这既是为了一致性,也是为了避免像
变量的声明和赋值不带
1 | var=10 |
指派。为了读取变量(换句话说,"展开"变量),必须使用
1 2 3 4 | $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脚本是不同的,
使用
1 2 3 | dir=(*) # store the contents of the directory into an array echo"${dir[0]}" # get the first entry. echo"$dir[0]" # incorrect |
您还可以在大括号内执行一些文本操作:
1 2 | STRING="./folder/subfolder/file.txt" echo ${STRING} ${STRING%/*/*} |
结果:
1 | ./folder/subfolder/file.txt ./folder |
或
1 2 | STRING="This is a string" echo ${STRING// /_} |
结果:
1 | This_is_a_string |
你在"规则变量"中是对的,不需要…但它对调试和读取脚本更有用。
变量名的结尾通常用空格或换行符表示。但如果在打印变量值后不需要空格或换行符呢?大括号告诉shell解释器变量名的结尾在哪里。
经典示例1)-不带尾随空格的shell变量1 2 3 4 5 6 7 | 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类路径
1 2 3 4 5 | # 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 |
(弗雷德的回答已经说明了这一点,但他的例子有点抽象)
访问数组元素和执行大括号扩展时总是需要大括号。
最好不要过于谨慎,即使没有歧义的余地,也可以使用
例如:
1 2 3 4 5 6 | 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 |
因此,最好将这三行写成:
1 2 3 | path=/var/$dir/$prog logfile=$path/$prog.log path_copy=$path |
这绝对是更可读的。
见:
- Linux环境变量名中允许的字符
根据Sierrax和Peter关于文本操作的建议,使用大括号
假设您有一个sposi.txt文件,其中包含一本意大利Weel已知小说的第一行:
1 2 | > sposi="somewhere/myfolder/sposi.txt" > cat $sposi |
输出:
现在创建两个变量:
1 2 3 4 5 | # 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文件中的一个新单词替换单词变量内容。
1 2 | > sed -i"s/${word}/${new_word}/g" $sposi > cat $sposi |
输出:
单词"ramo"已被替换。