Shell——语法
条件测试
1、测试命令:test和[,通过检查该类命令的退出码,决定条件测试是否成立
shell认为退出码为0,测试条件成立;非0,测试条件不成立
2、测试类型
(1)整数:-eq、-ne、-lt、-gt、-le、-lt
1 #!/bin/bash
2
3 read myint
4 test $myint -eq 100 #等于
5 echo $?
6 test $myint -ne 33 #不等
7 echo $?
8 test $myint -lt 35 #小于
9 echo $?
10 test $myint -gt 50 #大于
11 echo $?
12 test $myint -le 60 #小于等于
13 echo $?
14 test $myint -ge 66 #大于等于
15 echo $?
16 echo “\n”
17 [ $myint -eq 100 ] #等于
18 echo $?
19 [ $myint -ne 33 ] #不等
20 echo $?
21 [ $myint -lt 35 ] #小于
22 echo $?
23 [ $myint -gt 50 ] #大于
24 echo $?
25 [ $myint -le 60 ] #小于等于
26 echo $?
27 [ $myint -ge 66 ] #大于等于
28 echo $?
(2)字符串:==(=)、!=、-z、-n
1 #!/bin/bash
2
3 read mystring
4 [ mystring == "hello" ] #相等
5 echo $?
6 [ mystring != "hello" ] #不等
7 echo $?
8 [ -z mystring ] #判断字符串是否为空串,是空串返回1
9 echo $?
10 [ -n mystring ] #判断字符串是否为空串,是空串返回0
11 echo $?
什么都不输入时,输入的是空串。空串比较必须:左右字符串都加“”、左右两侧都加X
(3)文件:-d、-f、-b、-c
多条件测试
(1)逻辑非“!”
(2)逻辑与“-a”与 逻辑或“-o”用于连接两个测试条件
1 #!/bin/bash
2
3 #逻辑非
4 [ ! "Xmystring" == "hello" ]
5 echo $?
6
7 printf "please your data1:"
8 read d1
9 printf "please your data2:"
10 read d2
11 #逻辑与
12 [ $d1 -eq 100 -a $d2 -eq 200 ]
13 echo $?
14
15 #逻辑或
16 [ $d1 -eq 100 -o $d2 -eq 200 ]
17 echo $?
if/then/elif/else/fi实现分支控制
如果将两条命令写在同一行中要用“;”号隔开;
命令和参数之间要用空格隔开;if执行的子命令为0(真),执行then后面的,否则执行else后面的。
[aaa@qq.com shell]# cat if.sh
#!/bin/bash
printf "please data:"
read data
if [ $data -lt 100 ];then
if [ $data -eq 50 ];then
echo "data is eq 50"
elif [ $data -gt 50 ];then
echo "data is gt 50 and lt 100"
else
echo "data is lt 50"
fi
else
echo "data is gt 100"
fi
[aaa@qq.com shell]# /bin/bash if.sh
please data:43
data is lt 50
[aaa@qq.com shell]# /bin/bash if.sh
please data:50
data is eq 50
[aaa@qq.com shell]# /bin/bash if.sh
please data:67
data is gt 50 and lt 100
[aaa@qq.com shell]# /bin/bash if.sh
please data:104
data is gt 100
if的子命令除了“[”和“test”,还可以放其他的命令,只要其退出码为0或1
shell脚本中没有{}括号,所以用fi表示if语句块的结束
空代码块
在shell脚本中“:”是空命令,表示什么都不做
||和&&
用于连接两个命令
&&:相当于if...then
||:相当于if not...then
case/esac
相当于C语言中的switch....case,esac是case的结束标志,每个匹配分支可以有若干条命令但是末尾必须以“;;”结束,每个分支不需要break跳出
循环语句
1、for循环
类C for in循环
for...in组合
1 #!/bin/bash
2
3 for i in {1..5}{a..e}
4 do
5 echo $i
6 done
2、while 循环
[aaa@qq.com shel]$ vim while.sh
[aaa@qq.com shel]$ cat while.sh
#!/bin/bash
i=0
while [ $i -le 5 ]
do
echo "hello $i"
let i++
#((i++))
done
[aaa@qq.com shel]$ /bin/bash while.sh
hello 0
hello 1
hello 2
hello 3
hello 4
hello 5
3、until循环:shell特有的
[aaa@qq.com shel]$ vim until.sh
[aaa@qq.com shel]$ cat until.sh
#!/bin/bash
i=0
until [ $i -ge 5 ]
do
echo "hello $i"
let i++
#((i++))
done
[aaa@qq.com shel]$ /bin/bash until.sh
hello 0
hello 1
hello 2
hello 3
hello 4
4、死循环
1 #!/bin/bash
2
3 #方式一
4 for (( ; ; ))
5 do
6 echo "hello world!"
7 done
8
9 #方式二
10 while :
11 do
12 echo "hello world"
13 done
14
15 while true
16 do
17 echo "hello world"
18 done
19
20 #方式三
21 until false
22 do
23 echo "hello world"
24 done
shell代码块内绝对不允许包含空语句,一般用“:”代替空语句
5、命令行循环
【练习】求1—100的和
[aaa@qq.com shel]$ vim sum.sh
[aaa@qq.com shel]$ cat sum.sh
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
let sum+=i
let i++
done
echo $sum
[aaa@qq.com shel]$ /bin/bash sum.sh
5050
显示“+”和求的数字和其和
[aaa@qq.com shel]$ vim sum.sh
[aaa@qq.com shel]$ cat sum.sh
#!/bin/bash
i=1
sum=0
str=''
while [ $i -le 100 ]
do
let sum+=i
if [ -z "$str" ];then
str=$i
else
str=$str+$i
fi
let i++
done
echo $str=$sum
[aaa@qq.com shel]$ /bin/bash sum.sh
1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100=5050
求1—100之间的所有奇数的和
[aaa@qq.com shel]$ vim sum.sh
[aaa@qq.com shel]$ cat sum.sh
#!/bin/bash
i=1
sum=0
str=''
while [ $i -le 100 ]
do
let sum+=i
if [ -z "$str" ];then
str=$i
else
str=$str+$i
fi
let i+=2
done
echo $str=$sum
[aaa@qq.com shel]$ /bin/bash sum.sh
1+3+5+7+9+11+13+15+17+19+21+23+25+27+29+31+33+35+37+39+41+43+45+47+49+51+53+55+57+59+61+63+65+67+69+71+73+75+77+79+81+83+85+87+89+91+93+95+97+99=2500
位置参数和特殊变量
- $0、$1、$2...,称为位置参数,相当于C语言面main函数的argv[1],argv[2]...
- $#:相当于C语言main函数的argc-1,注意这里的#不表示注释
- aaa@qq.com:表示参数列表$1、$2
- $?:上一条命令的退出状态
- $$:当前shell的进程号
shift命令:位置参数可以用shift命令左移,不带参数的shift相当于shift 1
[aaa@qq.com shel]$ vim test.sh
[aaa@qq.com shel]$ cat test.sh
#!/bin/bash
echo "\$0->$0"
echo "\$1->$1"
echo "\$2->$2"
echo "\$3->$3"
echo "\$#->$#"
echo "\aaa@qq.com>aaa@qq.com"
echo "\$?->$?"
[aaa@qq.com shel]$ /bin/bash test.sh
$0->test.sh
$1->
$2->
$3->
$#->0
aaa@qq.com>
$?->0
[aaa@qq.com shel]$ /bin/bash test.sh arg1 arg2 arg3
$0->test.sh
$1->arg1
$2->arg2
$3->arg3
$#->3
aaa@qq.com>arg1 arg2 arg3
$?->0
[aaa@qq.com shel]$ vim test.sh
[aaa@qq.com shel]$ cat test.sh
#!/bin/bash
echo "----------shift 1 before---------"
echo "\$0->$0"
echo "\$1->$1"
echo "\$2->$2"
echo "\$3->$3"
echo "\$#->$#"
echo "\aaa@qq.com>aaa@qq.com"
echo "\$?->$?"
echo "----------shift 1 after---------"
shift 1
echo "\$0->$0"
echo "\$1->$1"
echo "\$2->$2"
echo "\$3->$3"
echo "\$#->$#"
echo "\aaa@qq.com>aaa@qq.com"
echo "\$?->$?"
[aaa@qq.com shel]$ /bin/bash test.sh arg1 arg2 arg3
----------shift 1 before---------
$0->test.sh
$1->arg1
$2->arg2
$3->arg3
$#->3
aaa@qq.com>arg1 arg2 arg3
$?->0
----------shift 1 after---------
$0->test.sh
$1->arg2
$2->arg3
$3->
$#->2
aaa@qq.com>arg2 arg3
$?->0
$0不移动,$1、$2移动一位,$3丢弃不要
遍历命令行参数
#!/bin/bash
#方式一
for i in aaa@qq.com
do
echo $i
done
#方式2
while [ $# -ne 0 ]
do
echo $1
shift 1 #位置参数左移一位
done
[aaa@qq.com shel]$ /bin/bash bl.sh arg1 arg2 arg3 arg4
函数
shell中的函数没有返回值和参数列表,shell脚本中的函数必须先定义后使用
1、函数传参:虽然shell函数没有参数,但是我们可以在调用函数时传任意多个参数,在函数内同样用$1、$2等变量来提取、$0并不会作为函数参数。改变函数中的位置参数不会影响函数外的变量。
1 #!/bin/bash
2
3 #注意:函数体的左花括号{和后面的命令之间必须有空格或换行
4 function fun()
5 {
6 #在函数定义时并不执行函数体内的命令,调用的时候才执行
7 echo "-----------------------"
8 echo $0
9 echo $1
10 echo $2
11 echo $3
12 echo $#
13 echo aaa@qq.com
14 echo "function"
15 echo "-----------------------"
16
17 }
18 #注意:最后一条命令和右花括号之间必须有换行或;
19
20
21 fun argv1 argv2 argv3 #函数调用不写括号
22 echo "--------shell----------"
23 echo $0
24 echo $1
25 echo $2
26 echo $3
27 echo $#
28 echo aaa@qq.com
29 echo "-----------------------"
2、函数返回值
(1)shell用$?来判定函数是否调用成功
- 函数调用或者返回时,将shell函数当命令
- 通过命令的退出码来判定命令的执行结果是否正确
- shell中if条件认为0为真,非0为假
- [、test 都是命令
(2)echo方式只关心它的数据,而不关心函数的退出码($()这种方式的函数里有且只输出一个)
shell脚本的调试方法
shell脚本的调试是通过选项来进行的
- -n:读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
- -v:一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
- -x:提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
这些选项的使用方法
- 一是在命令行中提供参数
- 二是在脚本开头提供参数
- 三是在脚本中用set命令启用或禁用参数
数组
shell只支持一维数组,初始化时不需要定义数组的大小。数组的下标是从0开始,可以使用连续的,也可以使用不连续的,而且下标没有范围限制,下标可以是整数或算术表达式,其值大于等于0。利用下标来获取数组中的元素。
语法格式:
3 #shell数组用括号表示
4 array_name=(value1 value2 value3 value4 ... valuen)
5 或
6 array_name[0]=""
7 array_name[1]=""
8 array_name[2]=""
9 array_name[3]=""
10 array_name[10]=""
3 arr=(1 2.32 'b' "string")
4
5 ${arr[index]} #读取数组指定元素的值
6
7 #获取数组中的所有的元素
8 ${arr[@]}
9 ${arr[*]}
10
11 #获取数组的长度
12 ${#arr[@]}
13 ${#arr[*]}
15 #遍历数组
16 for (( i=0;i < ${#arr[*]};i++))
17 do
18 echo "$i : ${arr[i]}"
19 done
20 for i in ${arr[*]}
21 do
22 echo $i
23 done
shell与文件
1、输出重定向:“>”
2、追加重定向:“>>”
3、输入重定向:“<”
【练习】给file文件中的每一行都添加字符串“buy”
[aaa@qq.com file]$ cat file
hello 0
hello 1
hello 2
hello 3
hello 4
[aaa@qq.com file]$ cat test.sh
#!/bin/bash
while read line
do
echo 'buy '$line
done < file >> file_b
[aaa@qq.com file]$ /bin/bash test.sh
[aaa@qq.com file]$ ls
file file_b test.sh
[aaa@qq.com file]$ cat file_b
buy hello 0
buy hello 1
buy hello 2
buy hello 3
buy hello 4
默认情况下:
- command > file 将stdout重定向到file,command < file 将stdin重定向到file
- find a 2>file将stderr重定向到file,find zhu 2>>file将stderr追加到file(2表示标准错误文件stderr)
- 将stdout和stderr合并后重定向到file
1 $command > file 2>&1
2 或
3 $command >> file 2&1
4、Here Document:用来将输入重定向到一个交互式shell脚本或程序
基本形式:
1 command << delimiter
2 document
3 delimiter
作用:是将两个delimiter之间的内容作为输入传递给command
- 结尾的delimiter一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和tab缩进
- 开始的delimiter前后的空格会被忽略掉
5、/dev/null文件:是一个特殊的文件,写入到它的内容会被丢弃;如果尝试从该文件读取内容,那么什么也得不到;将命令的输出重定向到它,可以起到“禁止输出”的效果
屏蔽stdout和stderr:
6、shell与信号
处理信号的方式:
- trap 'commands' signal-list,当脚本收到signal-list清单内列出的信号时,trap命令执行引导中的命令
- trap signal-list,trap不指定任何命令,接受信号的默认操作——结束进程的运行
- trap "signal-list,trap命令指定一个空命令串,允许忽视信号
7、shell文件包含
- .
- source
[aaa@qq.com file]$ ll
total 8
-rw-rw-r--. 1 admin admin 50 Jul 17 06:32 api.sh
-rw-rw-r--. 1 admin admin 123 Jul 17 06:34 test.sh
[aaa@qq.com file]$ cat api.sh
function intadd()
{
let data=$1+$2
echo $data
}
[aaa@qq.com file]$ cat test.sh
#!/bin/bash
. api.sh
read d1 d2
ret=$(intadd $d1 $d2)
echo $ret
source api.sh
read d1 d2
res=$(intadd $d1 $d2)
echo $res
[aaa@qq.com file]$ /bin/bash test.sh
15 23
38
29 32
61
shell运算符
1、echo
格式:echo string
string可以加"",也可以不加
换行:\n
不换行:\c
2、printf:ping命令模仿C程序。printf使用引用文本或空格分隔的参数,外面可以在printf中使用格式化字符串,还可以指定字符串的宽度、左右对齐方式
printf命令的语法:printf format-string [arguments...]
【练习】产生一个随机数
语法练习
1、编写进度条
1 #!/bin/bash
2
3 i=0
4 bar=''
5 label=("|" "/" "-" "\\")
6 while [ $i -le 100 ]
7 do
8 printf "[\e[43;46;lm%-100s\e[0m][%d%%][%c]\r" "$bar" "$i" "${label[i%4]}"
9 let i++
10 bar=${bar}'#'
11 sleep 0.1
12 done
13 printf "\n"
2、传入至少3个数,求最大值、最小值和平均值
1 #!/bin/bash
2
3 arr=(1 7 3 10 8 5 4 9 6 2)
4 let min=${arr[0]}
5 let max=${min}
6 sum=0
7 for (( i=0;i<${#arr[*]};i++))
8 do
9 [[ ${min} -gt ${arr[$i]} ]] && min=${arr[$i]}
10 [[ ${max} -lt ${arr[$i]} ]] && max=${arr[$i]}
11 let sum=sum+${arr[$i]}
12 done
13 echo $min
14 echo $max
15 echo $sum
16 total=${#arr[*]}
17 echo "$sum/$total" | bc
3、找规律并输出第100次会输出什么,0,1,1,2,3,5,8,13,21,34,55,89.........
4、反转文件