shell 运算符、控制结构和函数
shell运算符
- 原始 bash 不支持简单的数学运算符,但可以通过
awk或expr实现,expr命令常用,也可使用bc(需安装)
val=`expr 2 + 2` # 运算符要和表达式间要有空格,不能是 expr 2+2,写在 (()) 中不受此限制
# 假设 a=10,b=20
`expr $a + $b` # 30
`expr $a - $b` # -10
`expr $a \* $b` # 200
`expr $a / $b` # 2
`expr $a % $b` # 取余 0
a=$b # 把b的值赋给a
[ $a == $b ] # 数值比较 false
[ $a != $b ] # true
echo "2 + 3" | bc # 输出 5
echo "10 / 3" | bc # 输出: 3 除法默认只返回整数部分
echo "scale=4; 22 / 7" | bc # 输出: 3.1428 scale控制精度
# 进制转换,ibase:输入数字的进制,obase:输出数字的进制
echo "ibase=16; FF" | bc # 输出:255
条件表达式要放在方括号中,并且要有空格,[$a==$b]是错误的
- 关系、布尔、逻辑运算符
[ $a -eq $b ] # a==b equal
[ $a -ne $b ] # a!=b not equal
[ $a -ge $b ] # a≥b great equal
[ $a -le $b ] # a≤b less equal
[ $a -gt $b ] # a>b great than
[ $a -lt $b ] # a<b less than
[ ! false ] # ! 非运算
[ $a -lt $b -a $b -gt $a ] # -a 与运算 and
[ $a -lt $b -o $b -gt $a ] # -o 或运算 or
# 优先级:! > -a > -o
[ $a -lt $b && $b -gt $a ] # && 逻辑的and
[ $a -lt $b || $b -gt $a ] # || 逻辑的or
- 字符串运算符
# a="abc", b="efg"
[ $a = $b ] # a==b
[ $a != $b ] # a!=b
[ -z $a ] # 字符串长度为0返回true,a.size()==0
[ -n $a ] # 字符串长度不为0返回true,a.size()!=0
[ $a ] # 字符串不为空返回true a.isNotEmpty()
- 文件测试运算符
[ -b $file ] # file是块设备文件返回true
[ -c $file ] # file是字符设备文件返回true
[ -d $file ] # file是目录返回true
[ -f $file ] # file是普通文件返回true(既不是目录也不是设备文件)
[ -g $file ] # file设置了SGID位返回true
[ -k $file ] # file设置了粘着位(Sticky Bit)返回true
[ -p $file ] # file是有名管道返回true
[ -u $file ] # file设置了SUID位返回true
[ -r $file ] # file可读返回true
[ -w $file ] # file可写返回true
[ -x $file ] # file可执行返回true
[ -s $file ] # file为不为空返回true(文件大小大于0)
[ -e $file ] # file存在返回true(包括目录)
[ -S $file ] # file是socket文件返回true
[ -L $file ] # file存在并且是一个符号连接返回true
[ -t $fd ] # 检查文件描述符 fd 是否连接到一个终端
[ -v $var ] # 检查变量 var 是否设置(Bash 4.2+)
-
echo命令(会自动换行)- 显示普通字符:
echo "It is a test",可省略双引号echo It is a test - 显示转义字符:
echo "\"It is a test\"" - 显示变量:
echo "$var_name It is a test" - 显示换行:
echo -e "OK! \n It is a test" # -e 开启转义 - 显示不换行:
echo -n "OK! \n It is a test" # -n 不换行 - 显示结果定向至文件:
echo "It is a test" > myfile - 显示命令执行结果:
echo `date`
- 显示普通字符:
-
printf命令(不自动换行):printf format-string [args...]
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
%-10s:字符串,宽度为10个字符,-表示左对齐,没有则右对齐
%d:十进制整数
%-4.2f:浮点数,.2表示保留两位小数
%c:字符
%x:十六进制数
%o:八进制数
%b:二进制数
%e:科学计数法表示的浮点数
test命令:用于检查某个条件是否成立,对数值、字符和文件进行检测
a=100
b=200
if test $[a] -eq $[b]
then
echo '两数相等!'
else
echo '两数不相等!'
fi
# 输出:两数不相等! []执行基本的算数运算:res=$[a+b] res为300
控制流
if 语句
- 一个条件后就要跟一个
then,以fi结束(if的倒序)- 条件写在
[]中用-gt,-lt,-eq,例如:[ $a -gt $b ] - 条件写在
(())中可直接用>,<,=,例如:(( $a > $b ))
- 条件写在
# 多行写法
if condition; then
command1
else
commandN
fi
# 一行写法
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo 'true'; fi
if [ $a -gt $b ]
then
echo 'a > b'
elif [ $a -eq $b ]
then
echo 'a = b'
else
echo 'a < b'
fi
- 其中 condition 的“真/假”由命令的退出状态码(exit status)决定:退出码为 0 → 条件为真(true);退出码非 0 → 条件为假(false)
if 语句的几种形式
if [ ... ]:POSIX 兼容的测试命令(等价于test)[实际上是test命令(/usr/bin/[或内置命令),前后必须有空格。]不是独立命令,它是[命令的语法要求:最后一个参数必须是]- 不支持逻辑运算符
&&、||在[ ]内部直接使用(需用-a、-o,但已过时) - 变量建议加双引号,防止空值或含空格时报错。
- 字符串比较使用
=, !=,没有<, >, =~等运算符,数值使用-eq, -ne等,逻辑运算:-a, -o, !
if [[ ... ]]:Bash/Zsh 的增强测试(推荐在 Bash 中使用),是 Bash 内置语法,不是命令,更安全、功能更强。支持:- 通配符匹配:
==可用于模式匹配,如if [[ $var == file*.txt ]]; if [[ $var == $pattern ]],file*.txt, $pattern不能加双引号,会阻止通配符展开 - 正则表达式:
[[ $str =~ ^[0-9]+$ ]] - 逻辑运算符:
&&、||、! - 无需对变量加双引号(但仍建议加)
- 不会因分词或路径展开出错
- 不兼容 POSIX(
/bin/sh在 Debian/Ubuntu 下是 dash,不支持) - 对于字符串的比较使用
==/=, !=, >, <, =~,数值比较使用-ne, -eq, -ge等,逻辑运算:!, &&, ||
- 通配符匹配:
if (( ... )):整数算术条件判断- 专门用于整数的运算和比较
- 变量无需加
$(当然加了也可以) - 支持
==、!=、<、<=、>、>=、&&、||、!、位运算等 - 表达式结果非 0 → true;结果为 0 → false
- 仅适用于 Bash、Zsh 等,非 POSIX
if command; then:以命令的退出状态作为条件- 任何命令都可以作为条件!
if command:命令成功(exit 0)if ! command:命令失败(exit ≠ 0)if command1 && command2:两个都成功if command1 || command2:至少一个成功- 这是
if最本质的用法,其他[ ]、[[ ]]、(( ))都是特例。
for 循环
# 多行写法
for var in item1 item2 ... itemN
do
command1
command2
...
done
# 一行写法
for var in item1 item2 ... itemN; do command1; command2; ...; done
while、until 循环
while [until] [ $a -gt $b ] # : 冒号用于无限循环,也可使用 true,for (( ; ; ))
do
command
done
while read FILM # read 读取键盘信息,按<Ctrl-D>结束
do
echo "FILM = $FILM"
done
case 语句
- 每个
case分支以)开始,用;;表示 break,执行结束,esac作为结束标记(case的倒序)
case $var in
var1|var2|var3|...)
command1
...
;;
varN)
command2
...
;;
*) # 以上未匹配时捕获
command3
...
;;
esac
- 跳出循环
break:跳出所有循环(终止执行后面的所有循环)continue:跳出当前循环
shell 函数
# 函数定义
# 通过 $1 $2 ... $n 获取参数,当 n>=10 时,需使用 ${n} 获取参数
[ function ] fun (){
action;
[return int;]
}
# 函数调用 只需用函数名 fun
fun arg1 agr2 ... agrN
function关键字是可选的- 不加
return则以最后一条命令的运行结果作为返回值 - 显示加
return返回值只能是数值,介于(0-255) - 如果
return值超出255,直接使用echo输出而不是用return - 函数返回值在调用函数后通过
$?来获得 - 函数必须在使用前定义,一般放于脚本开始部分
欢迎大家关注我的微信公众号【扶锐随笔】

浙公网安备 33010602011771号