Shell脚本(下)

2020-03-19  本文已影响0人  chanzd

条件判断

if语句

if  condition
then
    statement(s)
fi

if  condition;  then
    statement(s)
fi

if else

if  condition
then
   statement1
else
   statement2
fi

if elif else

if  condition1
then
   statement1
elif condition2
then
    statement2
elif condition3
then
    statement3
……
else
   statementn
fi

命令的退出状态

每一条 Shell命令,不管是 Bash 内置命令(例如 test、echo),还是外部的 Linux 命令(例如 cd、ls),还是自定义的 Shell 函数,当它退出(运行结束)时,都会返回一个比较小的整数值给调用(使用)它的程序,这就是命令的退出状态(exit statu)

很多 Linux 命令其实就是一个C语言程序,熟悉C语言的读者都知道,main() 函数的最后都有一个return 0,如果程序想在中间退出,还可以使用exit 0,这其实就是C语言程序的退出状态。当有其它程序调用这个程序时,就可以捕获这个退出状态。

Shell test命令

Shell test 命令的用法为:
test expression
当 test 判断 expression 成立时,退出状态为 0,否则为非 0 值。

test 命令也可以简写为[],它的用法为:
[ expression ]
注意[]和expression之间的空格,这两个空格是必须的,否则会导致语法错误。[]的写法更加简洁,比 test 使用频率高。

test选项

文件类型判断

选项 作用
-b filename 判断文件是否存在,并且是否为块设备文件
-c filename 判断文件是否存在,并且是否为字符设备文件
-d filename 判断文件是否存在,并且是否为目录文件
-e filename 判断文件是否存在
-f filename 判断文件是否存在,并且是否为普通文件
-L filename 判断文件是否存在,并且是否为符号链接文件
-p filename 判断文件是否存在,并且是否为管道文件
-s filename 判断文件是否存在,并且是否为非空

-S filename 判断文件是否存在,并且是否为套接字文件

文件权限判断

选项 作用
-r filename 判断文件是否存在,并且是否拥有读权限
-w filename 判断文件是否存在,并且是否拥有写权限
-x filename 判断文件是否存在,并且是否拥有执行权限
-u filename 判断文件是否存在,并且是否拥有SUID权限
-g filename 判断文件是否存在,并且是否拥有SGID权限
-k filename 判断文件是否存在,并且是否拥有SBIT权限

文件比较

选项 作用
filename1 -nt filename2 判断 filename1 的修改时间是否比 filename2 的新
filename1 -ot filename2 判断 filename1 的修改时间是否比 filename2 的旧
filename1 -ef filename2 判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法

数值比较

选项 作用
num1 -eq num2 判断 num1 是否和 num2 相等。
num1 -ne num2 判断 num1 是否和 num2 不相等。
num1 -gt num2 判断 num1 是否大于 num2 。
num -lt num2 判断 num1 是否小于 num2。
num1 -ge num2 判断 num1 是否大于等于 num2。
num1 - le num2 判断 num1 是否小于等于 num2。

注意,test 只能用来比较整数,小数相关的比较还得依赖 bc 命令。

字符串相关

选项 作用
-z str 判断字符串 str 是否为空。
-n str 判断字符串 str 是否为非空。
str1 = str2 str1 == str2 =和==是等价的,都用来判断 str1 是否和 str2 相等
str1 !=str2 判断 str1 是否和 str2 不相等
str1 > str2 判断 str1 是否大于 str2。>是>的转义字符,这样写是为了防止>被误认为成重定向运算符。

str1 < str2 判断 str1 是否小于 str2。同样,<也是转义字符。

逻辑运算相关

选项 作用
expression1 -a expression 逻辑与,表达式 expression1 和 expression2 都成立,最终的结果才是成立的。
expression1 -o expression2 逻辑或,表达式 expression1 和 expression2 有一个成立,最终的结果就成立。
!expression 逻辑非,对 expression 进行取反。

当你在 test 命令中使用变量时,我强烈建议将变量用双引号""包围起来,这样能避免变量为空值时导致的很多奇葩问题

test 命令比较奇葩,>、<、== 只能用来比较字符串,不能用来比较数字,比较数字需要使用 -eq、-gt 等选项;不管是比较字符串还是数字,test 都不支持 >= 和 <=。有经验的程序员需要慢慢习惯 test 命令的这些奇葩用法。

对于整型数字的比较,我建议大家使用 (())

[[]]

[[ ]] 的用法为:
[[ expression ]]
当 [[ ]] 判断 expression 成立时,退出状态为 0,否则为非 0 值。注意[[ ]]和expression之间的空格,这两个空格是必须的,否则会导致语法错误。

[[ ]] 是 Shell 内置关键字,不是命令,在使用时没有给函数传递参数的过程,所以 test 命令的某些注意事项在 [[ ]] 中就不存在了,具体包括:
不需要把变量名用双引号""包围起来,即使变量是空值,也不会出错。
不需要、也不能对 >、< 进行转义,转义后会出错

[[]]支持逻辑运算符

[[ -z $str1 || -z $str2 ]]不能用-o -a选项

[[]]支持正则表达式

在 Shell [[ ]] 中,可以使用=~来检测字符串是否符合某个正则表达式,它的用法为:
[[ str =~ regex ]]

但是 [[ ]] 对数字的比较仍然不友好,所以我建议,以后大家使用 if 判断条件时,用 (()) 来处理整型数字,用 [[ ]] 来处理字符串或者文件。

shell case in

case expression in
    pattern1)
        statement1
        ;;
    pattern2)
        statement2
        ;;
    pattern3)
        statement3
        ;;
    ……
    *)
        statementn
esac

case、int 和 esac 都是 Shell 关键字,expression 表示表达式,pattern 表示匹配模式。

case 会将 expression 的值与 pattern1、pattern2、pattern3 逐个进行匹配:

case in 与正则表达式

格式 说明
* 表示任意字符串
[abc] 表示 a、b、c 三个字符中的任意一个。比如,[15ZH] 表示 1、5、Z、H 四个字符中的任意一个。
[m-n] 表示从 m 到 n 的任意一个字符。比如,[0-9] 表示任意一个数字,[0-9a-zA-Z] 表示字母或数字。
竖线 表示多重选择,类似逻辑运算中的或运算。比如,abc 竖线xyz 表示匹配字符串 "abc" 或者 "xyz"。

while

while 循环的用法如下:

while condition
do
    statements
done

until

until condition
do
    statements
done

for

for((exp1; exp2; exp3))
do
    statements
done

for in

for variable in value_list
do
    statements
done

select in

select variable in value_list
do
    statements
done

break

break n

continue

continue n

函数

function name() {
    statements
    [return value]
}

Shell 函数的返回值只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。

重定向

与输入输出有关的文件描述符

文件描述符 文件名 类型 硬件
0 stdin 标准输入 键盘
1 stdout 标准输出 显示器
2 stderr 标准错误输出 显示器

输出重定向

类型 符号 作用
标准输出重定向 命令>文件 以覆盖的方式,把命令的正确输出结果输出到指定的文件或设备中。
标准输出重定向 命令>>文件 以覆盖的方式,以追加的方式,把命令的正确输出结果输出到指定的文件或设备中。
标准错误输出重定向 命令 2> 文件 以覆盖的方式,把命令的错误信息输出到指定的文件或设备中。
标准错误输出重定向 命令 2>> 文件 以追加的方式,把命令的错误信息输出到指定的文件或设备中。
正确输出和错误信息同时保存 命令 > 文件2 > &1 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件中。
正确输出和错误信息同时保存 命令 >> 文件 2> &1 以追加的方式,把正确输出和错误信息同时保存到同一个文件中。
正确输出和错误信息同时保存 命令 &> 文件 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件中。
正确输出和错误信息同时保存 命令 &>> 文件 以追加的方式,把正确输出和错误信息同时保存到同一个文件中。
正确输出和错误信息同时保存 命令 >> 文件1 2>> 文件2 把正确的输出追加到文件1中,把错误信息追加到文件2中。

输入重定向

符号 说明
命令 < 文件 将指定的文件作为命令的输入。
命令 << 分界符 从标准输入(键盘)中读取数据,直到遇见分界符才停止。
命令 < 文件1 > 文件2 将文件1作为命令的输入,并将命令的处理结果输出到文件2。

shell模块化

source
source filename
. filename
避免循环导入

模块文件 module.sh:

if [ -n "$__MODULE_SH__" ]; then
    return
fi
__MODULE_SH__='module.sh'
echo "http://c.biancheng.net/shell/"

主文件 main.sh:

#!/bin/bash
source module.sh
source module.sh
echo "here executed"

运行 main.sh,输出结果为:
http://c.biancheng.net/shell/
here executed
上一篇 下一篇

猜你喜欢

热点阅读