shell脚本就是将一堆命令和特有的控制语句放入到.sh结尾的文件中,这个文件就被叫做shell脚本。
【1】shell脚本中的变量
(1)变量不需要定义
(2)变量没有对应的类型
(3)变量赋值的时候直接写=,
(4)在shell脚本中所有的变量被赋的值都认为是字符串
(5)赋值的区别如下:
var1=123 //字符串中不能有空格
var1='123 456' //可以有空格
var1="123 456 $var1" //可以有空格,可以调用新的变量
(6)变量的引用
$var1 ${var1}
(7)使用echo来打印变量
echo ${var1}
echo ${var2}
echo ${var3}
(8) 通过位置变量可以进行命令行的传递参数
$0
//脚本的名字
$1 $2 $3 $4.......$9 ${10}....${n}
//参数对应位置的字符串
$@或者$* //命令行传递所有的参数,脚本名除外
$# //命令行参数的个数
(9) 变量的其它用户
unset 变量名 //清除变量的值
readonly 变量名 //这个变量是只读的,变量在进行二次赋值的时候不需要加$符号
【2】shell脚本中的数组
shell脚本中只有一维数组,没有多维数组,数组没有成员个数的限制
(1) 数组的格式如下:
arr=(1 2 3 4 "helloworld")
arr=([0]=11 [5]=www)
(2)数组访问成员的方法
${arr[0]} ${arr[n]} //访问数组中的某一个成员
${arr[@]} 或者 ${arr[*]} //访问数组中所有的成员
${#arr[@]} 或者 ${#arr[*]} //数组中成员的个数
${#arr[n]} //第n个成员中保存字符的个数
(3)数组成员的追加
arr=(${arr[@]} "www.baidu.com") //在数组的尾部追加
arr[6]="www.github.com" //对数组的某个成员赋值
【3】 shell中的运算符
算术运算符 说明/含义
+ - 加法(或正号)、减法(或负号)
* / % 乘法、除法、取余(取模)
** 幂运算
++ -- 自增和自减,可以放在变量的前面也可以放在变量的后面
! && || 逻辑非(取反)、逻辑与(and)、逻辑或(or)
< <= > >= 比较符号(小于、小于等于、大于、大于等于)
== != = 比较符号(相等、不相等;对于字符串,= 也可以表示相当于)
<< >> 向左移位、向右移位
~ | & ^ 按位取反、按位或、按位与、按位异或
= += -= *= /= %= 赋值运算符,例如 a+=1 相当于 a=a+1,a-=1 相当于 a=a-1
shell中的变量都是被赋的值都是字符串,所以它不能
够进行算数运算。如果想执行算数运算必须使用特殊的
标识来完成。
(()) 整数运算
$[] 整数运算
expr 整数运算,字符串的运算
(1)(()) 如何使用
(($var1 + $var2))
((var1 + var2))
[1] 在(())内部变量前可以有$,也可以没有$符号,在运算符前后可以加空格,也可以不加空格
sum=$((var++))
[2]如果要将一个表达式的节骨赋值给变量,需要在(())前面加$符号
tt=$((表达式1,表达式2,表达式3,...))
[3]所有表达式都会参与运算,最后一个表达式的结果会被赋值给变量
[4]在(())中可以做复杂的运算
for((i=0;i <=100;i++))
{
((sum+=i))
}
echo $sum
(2)$[]如何使用
var1=12
ret=$[var1++]
echo $[var1++]
[1] $[]移动需要有变量去承接结果,不想让变量接受结果,就必须使用echo打印显示
ret=$[var2+var3]
echo $ret
[2] 在$[]内部,可以加$,也可以不加,运算符前后可以有空格
[3] 在$[]内部不允许做复杂运算,比如for循环
ret=$[var1++,var2++,var3++,3**5]
echo $ret
[4] 最后一个表达式的结果就是整个表达式的结果
(3)expr的使用
var1=12
var2=13
expr $var1 + $var2
[1]expr在运算完之后的结果会自动显示
[2]expr在使用变量之前,变量前一定要有$符号
[3]运算符前后必须要有空格,如果不加空格会出错
sum=`expr $var1 + $var2`
echo $sum
(4)如果将expr运算的结果赋值给新的变量,需要使用命令置换
mul=`expr $var1 \* $var2`
echo $mul
(5)expr在进行*运算的时候,如果不加转义字符,它认为是通配符号,不能进行*
注:如果将一个命令执行的结果赋值给一个变量,使用命令置换符号
var1=`ls`
var1=$(ls)
echo $var1
(6)使用expr求字符串的长度
expr length $var2
(7)用expr在源字符串中查找子字符的位置
expr index $var2 "字符"
如果第一个字符没有在源字符串中出现,就会去查找下一个字符,直到找到字符在源字符串中的位置
如果没有找到,返回0
(8)提取字符串
expr substr $var1 起始位置 结束位置
从其实位置开始截取$var1中的字符,直到字符位置结束
(9)字符串的匹配
expr match $var1 "子字符串"
从左侧第一个字符开始进行匹配,如果匹配成功了,返回匹配成功的字符的个数,
否则返回0,如果有任意一个匹配不上,就返回0.
[4] shell中的注释
#:单行注释
:<<EOF
被注释掉的部分
EOF
[5]shell中的控制语句
(1)if的语法格式
if [ 判断条件 ] ------>这里的[]又可以写成test
then
if成立时执行的语句
fi
if [ 判断条件 ]
then
if成立时执行的语句
elif [ 判断条件 ]
then
判断条件2成立时执行的语句
else
上述条件都不成立执行的语句
fi
[1]对数字的判断
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
[2]逻辑运算
&& ------> -a
|| ------> -o
! ------> !整体取反
[6] shell脚本中的输入命令
read 变量名 ---->类似于C中的scanf,c++中的cin
(1)将变量从终端读到shell脚本中
read 变量1 变量2 ..
(2)read可以同时读取多个变量的值
(3)read可以跟一个-p参数,在读取数据的时候,做打印提示信息
read -p "iput var1 var2" var1 var2
read -p "iput var1 var2" -a arr
echo ${arr[@]}
(4)read可以通过-a参数读取一个数组
read -n num var1
(5) read加-n 指定读取num个字符
read -p "passwd:" -s var
(6)read 加-s输入的数据不会回显(静默模式)
read -p "passwd:" -t 3 var1
(7)在sec秒之内如果没有输入,read会向下执行,如果有输入,就读取输入的数据
[7] shell中的输出
echo:
-n:不换行
-e:解析转移转义字符(\n)
printf:
用法跟c一样,例如:
printf "%d %s\n" $var1 $var2
[8]shell中判断的使用
(1)对数字的判断
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
(2) 逻辑运算
&& ----> -a
|| ----> -o
! ----> !
(3) 对字符串的判断
-z 判断字符串是否为空
-n 判断字符串是否不为空
=或者== 判断是否相等
!= 判断是否不相等
\> 判断是否大于
\< 判断是否小于
(4)对文件类型的判断
-e 判断文件是否存在
-s 判断文件是否存在,并判断文件是否为空
-b 判断文件是否存在,并判断文件是块设备
-c 判断文件是否存在,并判断文件是否为字符设备
-d 判断文件是否存在,并判断文件是否为目录
-f 判断文件是否存在,并判断文件是否是普通文件
-L 判断文件是否存在,并判断文件是否为链接文件
-S 判断文件是否存在,并判断文件是否为套接字文件
-p 判断文件是否存在,并判断文件是否为管道文件
(5)对文件权限的判断
-r:判断是否具备读的权限
-w:判断是否具备写的权限
-x:判断是否具备可执行的权限
[9] case in 语句
case 变量 in
选项1)
语句1
;;
选项2)
语句2
;;
*)
语句n
;;
esac
【1】循环语句
(1)while循环
语法格式如下:
while 循环条件
do
循环体
done
【2】 for循环
[1]for循环的第一种用法(类似C语言风格的for循环)
for((i = 0;i < 100;i++))
do
循环体
done
[2] for循环的第二种用法(shell特有的for循环)
for 变量 in 单词列表
do
循环体
done
注:单次列表的格式
格式1:ubuntu,windows,ios,macos,android
格式2:·ls·
格式3:{start..end}
格式4:如果in后面的单次列表都缺省,此时单次列表是命令行参数。
【3】select in 增加交互效果的循环语句
select 变量 in 单次列表
do
循环体
done
eg:
1-select.sh
2-select_case.sh
[4] break和continue
它和C语言用法一样的,只不过可以进行如下的是哟个:
break n 退出n层循环
continue n 跳过n层循环,进而执行下一次循环
goto用法:一般在程序中不建议使用。
【4】shell脚本中的函数
语法格式:
function 函数名()
{
return;
}
(1)function在shell中声明的是一个函数
(2)shell中的函数没有返回值类型
(3)shell中的函数没有参数列表,它可以传参
(4)shell中的函数体也是通过{}来表述的
(5)shell中的return在返回数的时候只能返回[0-255]
(6)在执行脚本的时候函数不会主动执行,需要主动调用函数,函数才能执行
---------------------------------------------------------------------------------------------------------------------------------
如下代码:
#!/bin/bash
year=2021
month=2
day=28
hour=23
min=59
sec=57
for ((;;))
{
((sec++))
if [ $sec -ge 60 ]
then
((min++))
((sec=0))
if test $min -ge 60
then
((min=0))
((hour++))
if test $hour -ge 24
then
((hour=0))
((day++))
if ((month==1||month==3||month==5||month==7||\
month==8||month==10||month==12))
then
if test $day -gt 31
then
((day=1))
((month++))
fi
elif ((month==4||month==6||month==9||month==11))
then
if test $day -gt 30
then
((day=1))
((month++))
fi
elif ((month==2))
then
if (((year%4==0&&year%100!=0)||(year%400==0)))
then
if test $day -gt 29
then
((day=1))
((month++))
fi
else
if test $day -gt 28
then
((day=1))
((month++))
fi
fi
else
echo "month error,try again"
fi
fi
if test $month -gt 12
then
((month=1))
((year++))
fi
fi
fi
printf "%d-%02d-%02d %02d:%02d:%02d\r" $year $month $day $hour $min $sec
sleep 1
}