Bash 参数扩展
如果您使用 bash,您已经知道什么是参数扩展,尽管您可能在不知其名称的情况下使用过它。任何时候您使用美元符号后跟变量名,您都在执行 bash 所谓的参数扩展,例如echo $a或者a=$b。但是参数扩展还有许多其他形式,允许您扩展参数并修改值或在扩展过程中替换其他值。
参数扩展在 bash 中有多种形式,最简单的是美元符号后跟名称,例如$a。这种形式只是将变量的值替换到参数扩展表达式的位置。变量名也可以选择用花括号括起来,例如${a}。如果变量名紧随其后的是可以作为变量名一部分的字符,则需要使用花括号来分隔变量名,例如,如果您从以下代码中删除花括号echo ${a}bcbash 将尝试扩展变量 "abc" 而不是 "a"。
参数扩展的一个有用形式是为变量设置默认值(如果变量未设置)。这可以通过以下语法完成${VAR:-DFLT}。您可以使用此功能来允许通过环境变量修改您的代码。考虑以下脚本,命名为test.sh:
TEST_MODE=${TEST_MODE:-0} ... if [[ $TEST_MODE -eq 0 ]]; then echo "Running in live mode" else echo "Running in test mode" fi通常脚本以 "live" 模式运行,但如果您通过以下方式运行它
$ env TEST_MODE=1 sh test.sh它将在测试模式下运行。
您还可以将默认值扩展与命令行参数或配置文件中的值一起使用,例如
# set cmd_param_x to 1 if seen on the command line ... if [[ ${cmd_param_x:-0} -eq 0 ]]; then echo "-x not specified" else echo "-x specified" fi
参数扩展的另一个有用形式是扩展变量并在值上执行字符串替换,使用以下形式${VAR/search/replace}。例如
VAR=aabbcc echo ${VAR/b/-dd-}输出 "aa-dd-bcc"。请注意,只替换搜索字符串的第一个实例,如果您想替换所有实例,请使用双斜杠
VAR=aabbcc echo ${VAR//b/-dd-}现在输出 "aa-dd--dd-cc"。
还有用于删除前缀和后缀的扩展。形式${VAR#pattern}从扩展值中删除与模式匹配的任何前缀。删除的前缀是最短匹配的前缀,如果您使用双井号/哈希标记,则删除最长匹配的前缀。类似地,形式${VAR%pattern}删除匹配的后缀(单百分号表示最短后缀,双百分号表示最长后缀)。例如
file=data.txt echo ${file%.*} echo ${file#*.}分别输出文件基本名称和扩展名(“data” 和 “txt”)。
注意:如果您难以记住这两个语法的哪个是哪个,“#” 键在键盘上位于 “%” 键的左侧,就像前缀在后缀之前一样。另请注意,这些是 *glob* 模式,而不是正则表达式。
存在的另一个扩展是从扩展值中提取子字符串,使用以下形式${VAR:offset:length}。这以预期的形式工作:偏移量从零开始,如果您未指定长度,则会延伸到字符串的末尾。例如
str=abcdefgh echo ${str:0:1} echo ${str:1}输出 “a” 和 “bcdefgh”。
这种形式也接受从字符串末尾向后计数的负偏移量。所以这个
str=abcdefgh echo ${str:-3:2}产生 “abcdefgh”... 哎呀,那里发生了什么?发生的事情是 bash 误解了我们想要的内容,因为扩展看起来像默认值扩展${VAR:-DFLT}。第一次我尝试这个时,我盯着它看了很长时间,才明白如何做到这一点(不使用变量 [见下文])
str=abcdefgh echo ${str:$((-3)):2}输出所需的值 “fg”。 “$((…))” 使 bash 将该值视为算术扩展(即数字)。另一种稍长的方法是
str=abcdefgh i=-3 echo ${str:$i:2}
我要提到的参数扩展的最后一种形式是简单地扩展为变量值的长度,其形式为${#VAR}。所以例如
str=abcdef echo ${#str}输出 “6”。
在您的 shell 脚本中使用这些形式的参数扩展可以简化和缩短您的脚本。这些不是 bash 支持的唯一参数扩展形式,但它们是我随着时间推移发现最有用的形式。有关更多信息,请参阅 bash 手册页的 “Parameter Expansion” 部分。
附注:请注意,上述所有形式的参数扩展也适用于 bash 的 *特殊参数*:“$$”、“$0”、“$1” 等。