源码在这里Github(forked from shehaodan/full-shell-demo)
- 数学计算
- 条件语句
- 循环语句
- 函数
数学计算
不能直接进行算数运算,要用数学计算(( ))命令,用$(( ))获取表达式的结果
echo 2+8 # 输出 2+8 被当做字符串处理了 a=$((10+66)) b=$((a-15)) c=$((a+b)) # 注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果 echo $c # 137 echo $((c+13)) # 150
也可以使用let用于整数运算,和(())类似。如果let后面的表达式中有例如|等特殊字符,需要用双引号” “或者单引号’ ‘将表达式包围起来。
echo let 1+2 # 错误,echo会把 let a+b作为一个字符串输出 let c=1+2 echo ${c} # 3
条件语句
if语法:
if condition1 then statement1 elif condition2 then statement2 elif condition3 then statement3 else statement4 fi
test是内置命令,用来检测某个条件是否成立。通常和if语句一起使用,大部分if语句都依赖test。test 命令有很多选项,可以进行数值、字符串和文件三个方面的检测。
test expression # 当expression成立时,退出状态为 0,否则为非 0 值 [ expression ] # 简写,注意[]和expression之间的空格
与文件类型相关的test选项:
-b filename:判断文件是否存在,并且是否为块设备文件
-c filename:判断文件是否存在,并且是否为字符设备文件
-d filename:判断文件是否存在,并且是否为目录文件
-e filename:判断文件是否存在
-f filename:判断文件是否存在,井且是否为普通文件
-L filename:判断文件是否存在,并且是否为符号链接文件
-p filename:判断文件是否存在,并且是否为管道文件
-s filename:判断文件是否存在,并且是否为非空
-S filename:判断文件是否存在,并且是否为套接字文件
与文件权限相关的test选项:
-r filename:判断文件是否存在,并且是否拥有读权限
-w filename:判断文件是否存在,并且是否拥有写权限
-x filename:判断文件是否存在,并且是否拥有执行权限
-u filename:判断文件是否存在,并且是否拥有 SUID 权限
-g filename:判断文件是否存在,并且是否拥有 SGID 权限
-k filename:判断该文件是否存在,并且是否拥有 SBIT 权限
与文件比较相关的test选项:
filename1 -nt filename2:判断 filename1 的修改时间是否比 filename2 的新
filename1 -ot filename2:判断 filename1 的修改时间是否比 filename2 的旧
filename1 -ef filename2:判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法
与数值比较相关的test选项(test只能用来比较整数,小数相关的比较还得依赖bc命令):
num1 -eq num2:判断 num1 是否和 num2 相等
num1 -ne num2:判断 num1 是否和 num2 不相等
num1 -gt num2:判断 num1 是否大于 num2
num1 -lt num2:判断 num1 是否小于 num2
num1 -ge num2:判断 num1 是否大于等于 num2
num1 -le num2:判断 num1 是否小于等于 num2
与字符串相关的test选项:
-z str:判断字符串 str 是否为空
-n str:判断字符串 str 是否为非空
str1 = str2,str1 == str2:=和==是等价的,都用来判断 str1 是否和 str2 相等
str1 != str2:判断 str1 是否和 str2 不相等
str1 \> str2:判断 str1 是否大于 str2。\>是>的转义字符,这样写是为了防止>被误认为成重定向运算符
str1 \< str2:判断 str1 是否小于 str2。同样,\<也是转义字符
与逻辑运算相关的test选项:
expression1 -a expression:逻辑与
expression1 -o expression2:逻辑或
!expression:逻辑非
[[ ]]是内置关键字,和test命令类似,也用来检测某个条件是否成立。支持正则表达式:
[[ expression ]] # 注意[[ ]]和expression之间的空格,这两个空格是必须的,否则会报错 #!/bin/bash read tel if [[ $tel =~ ^1[0-9]{10}$ ]] then echo "你输入的是手机号码" else echo "你输入的不是手机号码" fi
case in语句:
case expression in pattern1) statement1 ;; pattern2) statement2 ;; …… *) statement esac #!/bin/bash printf "Input integer number: " read num case $num in 1) echo "Monday" ;; 2) echo "Tuesday" ;; 3) echo "Wednesday" ;; 4) echo "Thursday" ;; 5) echo "Friday" ;; 6) echo "Saturday" ;; 7) echo "Sunday" ;; *) echo "error" esac #!/bin/bash printf "Input a character: " read -n 1 char case $char in [a-zA-Z]) printf "\nletter\n" ;; [0-9]) printf "\nDigit\n" ;; [,.?!]) printf "\nPunctuation\n" ;; *) printf "\nerror\n" esac
循环语句
while语句:
while condition do statements done
until语句:当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环
until condition do statements done
for语句:
# 形式1--c语言风格 for((exp1; exp2; exp3)) do statements done # 形式2--python风格 --for-in for variable in value_list do statements done
select in:用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能。select是无限循环(死循环),输入空值,或者输入的值无效,都不会结束循环,只有遇到break,或者按下 Ctrl+D 组合键才能结束循环。
select variable in value_list do statements done #!/bin/bash echo "What is your favourite OS?" select name in "Linux" "Windows" "Mac OS" "UNIX" "Android" do echo $name done echo "You have selected $name"
break,continue:break用来结束所有循环。continue用来结束本次循环
break n # n表示跳出循环的层数,如果省略n,则表示跳出当前的整个循环。 continue n
函数
函数在定义时可以不指明参数,但是在调用时却可以传递参数,并且给它传递什么参数它就接收什么参数。函数也不限制定义和调用的顺序,你可以将定义放在调用的前面。
返回值只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。如果函数体中没有return语句,那么使用默认的退出状态,也就是最后一条命令的退出状态。
#1 --> 普通写法 function name() { statements [return value] } #2 --> 简化写法 name() { statements [return value] } name # 调用函数 name param1 param2 param3 # 多个参数之间以空格分隔
如何得到函数的返回值:一种是借助全局变量,将得到的结果赋值给全局变量。一种是在函数内部使用 echo、printf 命令将结果输出,在函数外部使用$()或者“捕获结果。
#!/bin/bash function getsum() { local sum=0 # 局部变量 for((i=$1; i<=$2; i++)); do ((sum+=i)) done echo $sum return $? } read m read n total=$(getsum $m $n) # $()捕获了第一个echo的输出结果,它并没有真正输出到终端上 echo "The sum is $total" # 输入5,10,将打印出45