Bash 常用语法及相关概念
3.2 Shell 命令
3.2.4 复合命令
3.2.4.1 循环结构
until
until test-commands; do commands; done
while
while test-commands; do commands; done
for
for var in words; do pass ${var} to commands; done
#!/bin/bash
for i in 1 2 3 4 5
do
echo "Welcome $i times"
done
for output in $(Linux Command)
do
command1 on $output
command2 on $output
commandN
done
3.2.4.2 条件结构
if
if test-commands; then
commands;
elif test-commands; then
commands;
else
commands;
if
case
select
(())
((arithmetic expression))
对算术表达式求值,如果计算结果非零,则该测试返回状态为 0,否则返回状态为 1。
[[]]
[[conditional expression]]
对条件表达式求值,根据结果返回状态为 0 或 1。
3.2.4.3 命令组合
Bash 提供了两种方式来把一系列命令放在一起作为整体执行。命令组合在一起,可以对整个命令列表进行重定向。例如,命令列表中所有命令的输出都可以重定向到单一流中。
()
( list )
把一系列命令放在 () 中会创建一个subshell环境,并在subshell中执行每条命令。subshell结束后,该环境中的变量赋值不再有效。
{}
{ list; }
把一系列命令放在 {} 中会在当前shell中执行每条命令,不会创建subshell。命令列表最后的 ; 是必须的。
3.5 Shell 扩展
3.5.4 命令替换
命令替换用命令的输出取代命令本身。
$(command)
或
`command`
3.5.5 算术扩展
算术扩展可以对算术表达式求值并替换成的求值的结果。
$((arithmetic expression))
3.7 执行命令
3.7.5 退出状态
已执行命令的退出状态是 waitpid 系统调用或其等效函数的返回值。退出状态介于 0 到 255 之间,但是,如下所述,Shell可能会特别使用 125 以上的值。Shell的内置命令和复合命令的退出状态也限制在此范围内。在某些情况下,Shell将使用特殊值来指示具体的失败状态。
以Shell的角度看,命令执行成功,退出为 0。非0 退出表示失败。之所以使用这种不直观的方式,是因为可以很好的定义成功和各种失败状态。当命令以关键信号 $N$ 结束,Bash使用 128+N 的值作为退出状态。
如果找不到命令,执行该命令的子进程将返回状态 127。如果找到但不能执行该命令,则返回状态为 126 。
如果命令由于扩展或重定向期间的错误而失败,则退出状态 大于0。
退出状态用于 Bash 的条件命令(if, case, select, (()), [[]])和部分命令序列(cmd1 && cmd2, cmd1 || cmd2)。
Bash 的所有内部命令都会在成功时返回 0,失败时返回 非0,因此可用于条件命令和命令序列中。所有内建函数都返回退出状态 2 ,表示命令使用不正确,通常指选项无效或缺少参数。
6.4 Bash 条件表达式
条件表达式由复合命令 [[ 以及内部命令 test 和 [ 使用。
简短总结一下就是:
-
test实现了老式的,可移植的命令语法。在几乎所有的 shell 中 (除了最古老的 Bourne shell),[就是test的同义词,只是[需要参数]表示结尾。尽管所有现代 shell 都有[命令的内置实现,但系统依然有一个该名称的外部命令/bin/[。POSIX 为[定义了必需的功能集,但几乎所有 shell 都对其提供了扩展。因此,如果你想要可移植的代码,应当注意不要使用这些扩展。 -
[[是对test(或者[) 的增强,但它是 shell 语法中的关键字而不是一个命令。因其语法特性,你可以在其中使用&&和||进行布尔测试或者使用>和<进行字符串比较。[无法做到这些是因为它是个普通命令,而&&,||,<,>不能作为命令行参数传递给它。如果编写sh兼容的脚本,那么仍然需要使用[,如果使用了[[,要确保脚本开头有#!/bin/bashshebang 行。
| Feature | new test [[ |
old test [ |
Example |
|---|---|---|---|
| string comparison | > |
\> (*) |
[[ a > b ]] || echo "a does not come after b" |
< |
\< (*) |
[[ az < za ]] && echo "az comes before za" |
|
= (or ==) |
= |
[[ a = a ]] && echo "a equals a" |
|
!= |
!= |
[[ a != b ]] && echo "a is not equal to b" |
|
| integer comparison | -gt |
-gt |
[[ 5 -gt 10 ]] || echo "5 is not bigger than 10" |
-lt |
-lt |
[[ 8 -lt 9 ]] && echo "8 is less than 9" |
|
-ge |
-ge |
[[ 3 -ge 3 ]] && echo "3 is greater than or equal to 3" |
|
-le |
-le |
[[ 3 -le 8 ]] && echo "3 is less than or equal to 8" |
|
-eq |
-eq |
[[ 5 -eq 05 ]] && echo "5 equals 05" |
|
-ne |
-ne |
[[ 6 -ne 20 ]] && echo "6 is not equal to 20" |
|
| conditional evaluation | && |
-a (**) |
[[ -n $var && -f $var ]] && echo "$var is a file" |
|| |
-o (**) |
[[ -b $var || -c $var ]] && echo "$var is a device" |
|
| expression grouping | (...) |
\( ... \) (**) |
[[ $var = img* && ($var = *.png || $var = *.jpg) ]] && "echo "$var starts with img and ends with .jpg or .png" |
| Pattern matching | = (or ==) |
(not available) | [[ $name = a* ]] || echo "name does not start with an 'a': $name" |
| RegularExpression matching | =~ |
(not available) | [[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "It's Friday the 13th!" |
(*) This is an extension to the POSIX standard; some shells may have it, others may not.
(**) The -a and -o operators, and ( ... ) grouping, are defined by POSIX but only for strictly limited cases, and are marked as deprecated. Use of these operators is discouraged; you should use multiple [ commands instead:
if [ "$a" = a ] && [ "$b" = b ]; then ...if [ "$a" = a ] || { [ "$b" = b ] && [ "$c" = c ];}; then ...
各类文件测试操作符: -a, -b, -d, -e, -f, …
更多差异,可以参考以下链接: