shell脚本基础
所谓的shell脚本,就是一大串命令集合成一个文本运行,也就是说,我们可以将平时在交互模式下写的命令,编写成文件内容让其执行,当然,shell脚本也不单单只是将命令集合起来,脚本里面融入了像,循环,遍历,判断分支等强大的功能,
shell脚本的创建:
以.sh结尾的文件,如:newfile.sh ,
书写要求是第一行要写上解释这个shell脚本的解释器,通常的shell脚本的解释器都是bash,也就是这样,#!/bin/bash ,第一行除了写解释器路径,不能写其他的,然后第二行就为脚本的内容了,比如
vim file.sh #编辑器打开文件(如果没有就创建)
#!/bin/bash # 脚本第一行
# # 出第一行外的其他任意行,由#开头的行为注释行,
cat /etc/passwd # 查看/etc/passwd 内容
echo "hello world " # 输出 hello world
这就是一个简单的shell脚本,将在命令行执行的命令,写入文本文件中,
shell脚本的执行:
创建好了简单的shell脚本如何执行?有两种:
1,chmod +x file.sh # 给脚本加上一个执行权限就能直接执行了,命令行直接执行 ./file.sh 因为我们脚本的第一行指定了脚本的解释器,所以只要脚本有执行权限,就能直接执行了,
2,bash file.sh 通过bash命令来执行file.sh脚本,bash执行脚本有选项,
-n 检查脚本语法是否有错,
-x 显示执行步骤,
bash的流程控制语句: for if while until 都可以嵌套,
循环
for循环,语句格式
for VAR in 循环数列表(循环条件) do;# VAR是方便循环体调用的变量,
循环值
done
如 for i in {1..10};do #{1..10} 表示数字1-10就是循环的第二种方法,
sun= $[ $sun+$i ]
done
echo $sum
最后输出的$sum的结果为1+2+3..+10的和,
while循环:
while CONDITION; do
循环体
循环控制变量的修正表达式
done
当CONDITION为“真”进入循环,直到“假”退出循环;
比如:计算100以内数值之和;
until循环:
until CONDITION; do
循环体
循环控制变量修正表达式
done
当CONDITION为“假”时进入循环;为“真”退出循环;
计算100以内所有数之和;
条件判断
if / then
条件测试:(中括号和表达式之间要有空格)
[ EXPRESSION ]
` EXPRESSION `
整数测试:A, B
A -gt B: 大于
A -ge B: 大于等于
A -eq B: 等于
A -lt B: 小于
A -le B: 小于等于
A -ne B: 不等于
字符串测试:A, B
A > B
A < B
A >= B
A <= B
A == B或A = B:等值比较
A != B: 不等于
-z A: 判断A是否为空;空则为真,不空则假;
-n A:判断A是否不空;不空则为值,空则为假;
字符串比较 符号两边要有空格,
if的语句格式:
if [ 条件 ];then
循环体
fi
比如,测试172.16.100.*这个网段所有的ip联通率,
if结构的分支可以有很多,
if [ 条件 ];then
循环体
else
循环体
else
循环体
...
fi
case 就是简要版本的if多分支另一种形式,
语法格式:
case 变量引用 in
PATTERN1)
分支1
;;
PATTERN2)
分支2
;;
...
*)
分支n
;;
esac
扩展:
if循环里面的判断,条件测试;
字符串测试:=~
"$A" =~ PATTERN
如果变量A中保存的字符串能被PATTERN所匹配;即为真;否则为假;
文件测试:$file
-e $file: 是否存在;存在则为真;
-a $file: 同上;弃用;
-f $file: 文件是否存在,且为普通文件;
-d $file: 是否存在且为目录;
-h $file: 是否存在且为符号链接文件;
-L $file:同上
-b $file: 是否存在且为块设备文件;
-c $file: 是否存在且为字符设备文件;
-S $file: 是否存在且为套接字文件:
-p $file: 是否存在且为管道文件;
-r $file: 当前用户对此文件是否拥有读权限;
-w $file: 写
-x $file: 执行权限;
-u $file: 文件是否拥有suid权限;
-g $file:文件是否拥有sgid权限;
-k $file: 文件是否拥有sticky权限;
-O $file: 当前用户是否为文件的属主;
-G $file: 当前用户是否属于文件的属组;
-N $file: 文件自从上一次被读取之后,是否被修改过;
$f1 -nt $f2: 文件f1是否比文件f2新;
$f1 -ot $f2: 文件f1是否比文件f2旧;
$f1 -ef $f2: f1和f2是否为同一个文件的硬链接;
通过这些条件测试可以得知这文件是否存在?是否有内容?这目录是否存在,否则就创建, 组合测试条件:短路操作符
与:COMMAND1 && COMMAND2
COMMAND1的退出状态如果为假,则COMMAND2不用运行,即可有最终结果;
或:COMMAND1 || COMMAND2
COMMAND1的退出状态如果为真,则COMMAND2不用运行,即可有最终结果;
非:! COMMAND
# 如果根目录下存在目录tmd 就不创建,如果没有,就创建tmd
[ -d /tmd ] || mkdir /tmd
函数
函数就是将一段重复调用的代码合并到一起,通过调用函数来调用代码的执行,
函数的格式:
function f_name() {
重复调用的代码
}
f_name() #通过函数名来调用函数,
递归函数之阶乘函数:
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
#以后要用这个函数就调用fact执行他,
唯一要注意的是函数名和变量名的命名要区分开,比如函数名叫f_NAME 变量名为v_NAME
如果不分开命名 或许等一段时间后你自己都不知到fact是变量还是函数了。
数组
是一种键值对集合,array[ 0=>张三,1=>李四 ] ,输出array[ 0 ] 结果就为张三,
像上面的 0 1 称为键也叫做下标,张三,李四为值,他们是一对对出现的,
常见的两种数组形式,
数组调用:
${ARRAY[index]}
索引数组,
下标从0开始,0,1,2,,,,
关联数组,
自定义下标,array[ one=>张三,for=>李四 ] echo array[ for ]结果为李四,
数组赋值声明:
数组元素的赋值:
(1) 一次只赋值一个元素
ARRAY[index]=VALUE
a[0]="hello"
(2) 一次赋值全部元素
ARRAY=("mon" "tue" "wed")
(3) 指定索引进行赋值
ARRAY=([0]="sun" [1]="mon" [5]="fri")
(4) read -a ARRAY
read 是交互式输入,
# 用户输出的值赋给变量choice,-t是表示最多等7秒,7秒后跳出,
read -p -t 7 "Your choice: " choice
常见的数组操作,
从数组中挑选某元素:
${ARRAY[@]:offset:number}
对于:week=(mon tue wed thu fri sat sun)
${week[@]:3:2}结果为:
切片:
offset: 偏移过去的元素的个数;
number: 取出的元素的个数;
${ARRAY[@]:offset}
取出指定偏移量之后的所有元素;
${ARRAY[@]}, ${ARRAY[*]}
取出所有元素;
向数组中追加元素:非稀疏格式
week,
week[${#week[@]}]
从数组中删除元素:
unset ARRAY[index]
常见的字符串处理操作:
字符串切片:${var:offset:lenth}
a="world", ${a:2:2}, rl
取字符串最后的几个字符:${var: -lenth}
注意:冒号之后有空格;
基于模式取子串:
${var#*word}:其中word可以是指定的任意字符;
自左而右,查找var变量所存储字符中,第一次出现的word,
删除字符开头直至第一次wrod出现处之间的所有字符;
# mypath='sysconfig/network-scripts/ifcfg-eth0'
# echo ${mypath#*/}
network-scripts/ifcfg-eth0
${var##*word}: 其中word可以是指定的任意字符;
自左而右,查找var变量所存储字符中,最后一次出现的word,
删除字符开头直至最后一次wrod出现处之间的所有字符;
# mypath='/sysconfig/network-scripts/ifcfg-eth0'
# echo ${mypath##*/}
ifcfg-eth0
${var%word*}: 自右而左,删除第一次word出现处的字符开始直到尾部的所有字符;
${var%%word*}自右而左,删除最后一次word出现处的字符开始直到尾部的所有字符;
例子:url=http://www.magedu.com:80
取端口:${url##*:}
取协议:${url%%:*}
查找并替换:
${var/pattern/substi}:查找var所表示的字串中,
第一次被Pattern匹配到的字串,并以substi替换之;
${var//patten/substi}:查找var所表示的字串中,
所有被Pattern匹配到的字串,并以substi替换之;
${var/#pattern/substi}:以行首锚定的方式将pattern匹配至var所表示的字串上,
如果能匹配,则以substi替换之;
${var/%pattern/substi}:以行尾锚定的方式将pattern匹配至var所表示的字串上,
如果能匹配,则以substi替换之;
可使用?, *元字符;
查找并删除:
${var/pattern}:删除pattern匹配到的第一次出现;
${var//pattern}: 删除pattern匹配到的所有出现;
${var/#pattern}
${var/%pattern}
字符串大小写转换:
${var^^}:小写-->大写
${var,,}:大写-->小写