2004 年 7 月 27 日,Chet Ramey 发布了 Bash 版本 3。此更新修复了相当多的错误并添加了新功能。
一些更重要的新增功能
一个新的,更通用的 {a..z} 花括号扩展 运算符。
#!/bin/bash for i in {1..10} # Simpler and more straightforward than #+ for i in $(seq 10) do echo -n "$i " done echo # 1 2 3 4 5 6 7 8 9 10 # Or just . . . echo {a..z} # a b c d e f g h i j k l m n o p q r s t u v w x y z echo {e..m} # e f g h i j k l m echo {z..a} # z y x w v u t s r q p o n m l k j i h g f e d c b a # Works backwards, too. echo {25..30} # 25 26 27 28 29 30 echo {3..-2} # 3 2 1 0 -1 -2 echo {X..d} # X Y Z [ ] ^ _ ` a b c d # Shows (some of) the ASCII characters between Z and a, #+ but don't rely on this type of behavior because . . . echo {]..a} # {]..a} # Why? # You can tack on prefixes and suffixes. echo "Number #"{1..4}, "..." # Number #1, Number #2, Number #3, Number #4, ... # You can concatenate brace-expansion sets. echo {1..3}{x..z}" +" "..." # 1x + 1y + 1z + 2x + 2y + 2z + 3x + 3y + 3z + ... # Generates an algebraic expression. # This could be used to find permutations. # You can nest brace-expansion sets. echo {{a..c},{1..3}} # a b c 1 2 3 # The "comma operator" splices together strings. # ########## ######### ############ ########### ######### ############### # Unfortunately, brace expansion does not lend itself to parameterization. var1=1 var2=5 echo {$var1..$var2} # {1..5} # Yet, as Emiliano G. points out, using "eval" overcomes this limitation. start=0 end=10 for index in $(eval echo {$start..$end}) do echo -n "$index " # 0 1 2 3 4 5 6 7 8 9 10 done echo |
The ${!array[@]} 运算符,它扩展到给定数组的所有索引。
#!/bin/bash Array=(element-zero element-one element-two element-three) echo ${Array[0]} # element-zero # First element of array. echo ${!Array[@]} # 0 1 2 3 # All the indices of Array. for i in ${!Array[@]} do echo ${Array[i]} # element-zero # element-one # element-two # element-three # # All the elements in Array. done |
在双括号测试表达式中,=~ 正则表达式匹配运算符。(Perl 有类似的运算符。)
#!/bin/bash variable="This is a fine mess." echo "$variable" # Regex matching with =~ operator within [[ double brackets ]]. if [[ "$variable" =~ T.........fin*es* ]] # NOTE: As of version 3.2 of Bash, expression to match no longer quoted. then echo "match found" # match found fi |
或者,更实用的是
#!/bin/bash input=$1 if [[ "$input" =~ "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]" ]] # ^ NOTE: Quoting not necessary, as of version 3.2 of Bash. # NNN-NN-NNNN (where each N is a digit). then echo "Social Security number." # Process SSN. else echo "Not a Social Security number!" # Or, ask for corrected input. fi |
新的set -o pipefail选项对于调试 管道很有用。如果设置了此选项,则管道的退出状态是管道中最后一个失败(返回非零值)的命令的退出状态,而不是管道中实际的最后一个命令的退出状态。
请参见示例 16-43。
![]() | Bash 版本 3 的更新破坏了一些在早期版本下可以工作的脚本。测试关键的旧脚本以确保它们仍然可以工作! 碰巧的是,《高级 Bash 脚本指南》中的一些脚本不得不进行修复(例如,请参见示例 9-4)。 |
Bash 版本 3.1 的更新引入了许多错误修复和一些小的更改。
现在允许在以前只识别 = 赋值运算符的地方使用 += 运算符。
a=1 echo $a # 1 a+=5 # Won't work under versions of Bash earlier than 3.1. echo $a # 15 a+=Hello echo $a # 15Hello |
在这里,+= 用作字符串连接运算符。请注意,它在此特定上下文中的行为与 let 结构中的行为不同。
a=1 echo $a # 1 let a+=5 # Integer arithmetic, rather than string concatenation. echo $a # 6 let a+=Hello # Doesn't "add" anything to a. echo $a # 6 |
Jeffrey Haemer 指出,此连接运算符可能非常有用。在这种情况下,我们将一个目录附加到$PATH.
bash$ echo $PATH /usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin/:/usr/games bash$ PATH+=:/opt/bin bash$ echo $PATH /usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin/:/usr/games:/opt/bin |
这基本上是一个错误修复更新。
在 全局参数替换中,模式不再锚定在字符串的开头。
The--wordexp选项禁用进程替换。
=~ 正则表达式匹配运算符不再需要在 [[ ... ]] 中引用 模式。
![]() | 实际上,在这种情况下,不建议引用,因为它可能导致 regex 评估失败。Chet Ramey 在 Bash FAQ 中指出,引用会显式禁用 regex 评估。另请参见 Ubuntu Bug List 和 Wikinerds on Bash syntax。 在脚本中设置 shopt -s compat31 会导致恢复到原始行为。 |