一点总结
由于自己本身就对shell中常用的命令有所了解,所以基础的就不啰嗦了。在我之前的博客中已经有不少内容
就写过的很多shell脚本经验看,最近作为助教又在跟着霍格沃兹第三期,又有了新感受。结合以前的经验,做个简单的总结。
- 代码要规范
- 虽然是shell,代码在逻辑上也要缜密
Linux文本三剑客
awk
最基本的作用,按规则输出列。
前置学习printf 或print。
printf
命令格式:
printf ‘匹配式’ 输入内容
它的输出全部当成字符串。所以需要自己来设置换行或空格。
%ns
输出字符串。n是数字指代输出几个字符
%ni
输出整数。n是数字自带输出几个数字。
%m.nf
输出浮点数。m是总的位数,n是小数位数
下面是例子,文本demo.txt
ID Name Linux PHP MySQL Java
1 Liming 82 55 58 87
2 SC 82 65 72 77
3 Tg 88 83 93 75
下面的命令会无差别打印全部字符,没有任何分隔符。
1 2 3
| printf '%s' `cat demo.txt`
|
下面命令正常输出。
1
| printf '%s\t%s\t%s\t%s\t%s\t%s\t\n' `cat demo.txt`
|
awk句法
1
| awk '条件1{动作1} 条件2{动作2}...' 文件名
|
awk 是一行一行执行的,先第一行全部内容给$0,依次列给$N。依据条件类型判定动作执行,不断的迭代。
条件可以是以下:**
保留字BEGIN,awk程序尚未读取数据之前执行1次。
保留字END,awk处理完数据,即将结束执行1次。
没有条件
x > =10
x == y
A ~ B A中是包含B的字符串
A !~ B A中不包含B的字符串
1 2 3 4 5
| awk 'BEGIN{print "hellow world"} {printf $2 "\t" $6 "\n"}' demo.txt
awk '$2 ~ /Tg/ {print $3}' demo.txt
awk '/Tg/ {print $3}' demo.txt
|
动作可以是:
格式化输出
流程控制语句
awk常用内置变量
NF 当前拥有的的列总数
NR awk所处理的行,总行数据的第几行
$n 代表目前读入的第n个字段($0 $1….)
FS 定义分隔符,指定分隔符是个动作
1 2
| cat /etc/passwd |grep /bin/bash|awk 'BEGIN{FS=":"} {print $1}'
|
sed
用途:数据选、换、增、查。
句法
选项:
-n 处理过的数据才输入到屏幕,不加打印全部并加上处理过的。
-e 允许对输入数据多条sed操作
-f 从脚本读取sed操作
-r 支持正则
-i sed修改写回文件
动作:
a \ 追加。追加多行时,需要每行末尾用”\“代表数据未完。
c \ 行替换。追加多行时,需要每行末尾用”\“代表数据未完。
i \ 前插入。追加多行时,需要每行末尾用”\“代表数据未完。
p3 打印第三行。
d 删除
s 字符替换。格式“行范围s/旧字符/新字符/g”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| sed '2p' demo.txt sed -n '2p' demo.txt sed '2,4d' demo.txt sed '2c 11111' demo.txt sed 's/Liming/Limi/g ; s/Tg/TTTT/g' demo.txt
sed -e '2c 11111' -e '3c gogogo' demo.txt
url_avg_time(){ awk '{print $(NF-1), $7}' nginx.log | \ sed 's#\?.*##g' | \ sed 's#%21#\!#g' | \ sed 's#/\(topics\|replies\|avatar\)/[0-9]\+#/\1/int#g' | \ sed 's#\(.\+\)/[^/].*\(png\|jpg\|gif\|jpeg.*\)#\1/id\.\2#g' | \ sed 's# /[^/]\+/\(topics\|following\|replies\|columns\|favorites\|reward\|followers\)$# /username/\1#g' | \ sed 's#\.\(tar\.tgz\|tar\.gz\|tar\|gz\|zip\|rar\)$#\.compress#g' | \ sort -k 2 | \ awk '{total[$2]+=$1; times[$2]++;} END{for(url in total){avg=sprintf("%.3f", total[url]/times[url]); print(avg, url)}}' | \ sort -k 1 -nr | \ awk 'BEGIN{printf("%s\t%s\n", "平均响应时间", "接口地址")} {printf("%8s\t%s\n", $1, $2)}' }
|
grep
数据查找和定位。用得比较熟,略过。
资源
ps
ps查询出来cpu利用率的是时间范围内的平均值,不是实时
top
1 2
| top -hv|-bcHiOSs -d secs -n max -u|U user -p pid -o fld -w [cols]
|
常用套路
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
| top -p pid -H
top -b
ps -o %cpu,%mem -p 22056
perf_get() { local proc="$1" local timeout="$2" [ -z "$proc" ] && { echo please give a proc name or pid; return 1; } [ -z "$timeout" ] && timeout=10 top -b -d 1 -n $timeout | grep '^[ 0-9][1-9]' | awk '{print $1,$9,$10,$12}' | grep --line-buffered -i "$proc" | awk ' BEGIN{OFS="\t";print "CPU","MEM"} {cpu+=$2; mem+=$3;print $1,$2,$3,$4;} END{print "";print "avg: ",cpu/NR,mem/NR}' }
|
netstat
数组的套路
套路就是招式。。
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
| array=() array=(a b c)
b=${array[1]}
index=${!array[@]}
length=${#array[@]}
all_1=${array[@]} //数组 all_2=${array[*]} //字符串
for i in ${array[@]} do ${i} ... done
for i in ${!array[@]} do ${array[$i]} ... done
|
实战
需求
题一:
一家公司有N多人,老板要在年会上抽奖,编写一个脚本进行抽奖。模拟, 每个人掷骰子 。
输出每一轮的掷骰子的结果;
选出最后一个人。
题二:
增加输出参数N,为最后抽到的人数。如果没有抽足,则从未抽中人群中继续抽,直到抽完。输入同上。
抽奖题一
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
| function draw(){ local array=${1} local number=${2} local size=${#array[@]} local removed=() if [ ${size} -eq ${number} ] then { echo ${array[*]} return 0; } else { for i in "${!array[@]}"; do ((RANDOM%6+1 < 4)) removed[${#removed[@]}]=array[$i] unset array[$i]; done if [ ${#array[@]} -lt ${number} ] then printf ${array[*]}" " draw ${removed[@]} ((${number}-${#array[@]})) else draw ${array[@]} fi } fi } function lucky(){ number=${1} array=$(cat ~/username.txt |sort |uniq |grep -v ^$) draw ${array[@]} }
|
抽奖题二
第二个抽奖,递归
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
| function draw(){ local array=($*) local number=${array[${#array[@]}-1]} unset array[${#array[@]}-1] local size=${#array[@]} local removed=() if [ ${size} -eq ${number} ] then { echo "已中奖名单:"${array[*]} return 0; } else if [ ${#array[@]} -gt 0 ];then { for i in ${!array[@]}; do ((RANDOM%6+1 < 4)) && removed[${#removed[@]}]=${array[$i]} && unset array[$i] done if [ ${#array[@]} -lt ${number} ] then echo "已中奖名单如下。由于中奖人数不足,剩余人员抽继续抽取。。。" echo ${array[*]} draw ${removed[@]} $((${number} - ${#array[@]})) else draw ${array[@]} ${number} fi } fi fi } function lucky_top(){ number=${1} array=$(cat ~/username.txt |sort |uniq |grep -v ^$) draw ${array[@]} ${number} }
|
第二个抽奖,非递归方法
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
| function lucky_top2(){ number=${1} array=$(cat ~/username.txt |sort |uniq |grep -v ^$) [ 0 -eq ${number} ] && echo "不需要有人中奖" && return 0 [ ${#array[@]} -lt ${number} ] && echo "全部中奖:"${array[*]} && return 0 local removed=() while [ ${#selected[@]} -lt ${number} ];do local selected=() for i in ${!array[@]}; do ((RANDOM%6+1 > 3)) && selected[${#selected[@]}]=${array[$i]} && unset array[$i] done echo "已中奖名单如下。由于中奖人数不足,剩余人员抽继续抽取。。。" echo ${selected[@]} done }
|