花了两天看了下shell编程的一些内容,结合以前记得笔记做个小结。linux的shell编程主要是用于维护服务器操作的自动化,从安装软件,到启动服务,都可以使用脚本来完成。
前言
花了两天看了下shell编程的一些内容,结合以前记得笔记做个小结。linux的shell编程主要是用于维护服务器操作的自动化,从安装软件,到启动服务,都可以使用脚本来完成。
linux下的shell有很多种,但我们主要用的是bash
感觉下来,shell的一些优势:
- 不需要额外的环境,linux自带bash。
- 完成简单的操作需要的代码量较少。
- 和原生程序交互比较方便。比如处理文本的时候需要用到的awk和sed,熟练使用后比较方便。
语法基础
1. bash内置变量和常见表达式
- 命令行参数(非指定), 对于脚本参数,和自定义函数参数而言,$0代表脚本本身的名字,$1到$9代表1到9个参数,从第10个参数开始需要用${n}来表示变量。
- 常见的符号。$,取变量的值,${}和$()分别代表在在本身的shell中执行命令和在子shell中执行命令。{}还有分割变量与文本的左右例如$varAA就会报错,需要携程${var}AA的形式。
- 扩展运算,$[cmd],$((cmd))进行数字运算,`expr x operator y`也可能达到相同的效果。
- >>和<< 重定向,|管道。
- 定义数组 var=(),生成a到z的list,var=({a..z})
- 更多表达式参考 https://www.cnblogs.com/farwish/p/4806018.html
2. bash中的过程控制
- 分支选择
if分支选择语法cond 可用test命令1
2
3
4
5
6
7if [ cond ]; then
cmd
elif [ cond ];then
cmd
else
cmd
fi
例如 test -e /etc/passwd 或者 []代替test [ -e /etc/passwd ]
选择分支语法
1
2
3case word in
[ [(] pattern [| pattern]…) command-list ;;]…
esac
举例
1
2
3
4
5
6
7
8
9echo -n "Enter the name of an animal: "
read ANIMAL
echo -n "The $ANIMAL has "
case $ANIMAL in
horse | dog | cat) echo -n "four";;
man | kangaroo ) echo -n "two";;
*) echo -n "an unknown number of";;
esac
echo " legs."
循环
for循环1
2
3
4
5
6
7
8
9for var in list;
do
cmds;
done
for((exp1;exp2;exp3));
do
cmds;
donewhile循环和until循环
语法
1
while \ until [ test cmd ]; do cmds;done
while和until的唯一区别是until的退出条件是test命令返回1 也就是不成立循环,而while循环则相反
3. 处理字符串
- shell内置处理字符串,准确说shell中有两种处理字符串的方式。一种是${var:start:length},另外一种则是通过通配符的方式掐头去尾。
- 例如 ${var%%$SUBSTR},最长匹配去尾
- ${var##$SUBSTR},最长匹配去头
- ${var\$old\$new} 将旧的字符串替换为新的字符串(第一个) \\全部替换,#匹配开头,%匹配结尾
- cut命令 cut -f 1,7 -d ‘分隔符’ 去第一块和第七块
- awk -F ‘分隔符’ ‘条件{action}’ 文本
- sed
4. 一些实例
随机函数
array[@]或者array[*]取数组所有的变量,数组下标从1开始。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21get_random(){
length=$1
payload=({a..z})
payload+=({0..9})
l=${#payload[@]}
result=''
for((i=0;$i<$length;i++))
do
r=$[$RANDOM%$l]
result=$result${payload[$r-1]}
done
printf "\n"
echo $result
}
for i in `seq 1 20`
do
result=$(get_random 6)
echo $result
done统计每个ip的访问量并按从大到小排序
1
2
3
4
5! /bin/bash
path=$HOME
now=$(date +%Y%m%d)
echo $(ps aux | awk '{if($1 in map){map[$1]+=1}else{map[$1]=1}} END{for(x in map){printf("用户名:%-20s\t\t进程数:%d\r",x,map[x]) }}')>>$path/$now.log