一、这节课掌握如下几个知识点
【1】掌握awk数组的使用技巧
【2】掌握awk中BEGIN、END
【3】掌握awk的内置函数用法
二、代码讲解
本节的测试用例采用第7节的测试用例: 7.example.txt
#!/bin/bash
#8.sh v1
PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
export LANG=zh_CN.UTF-8
export PATH
#1.数组
awk 'BEGIN{a[0]="xiaohong";a[1]="xiaolan";for (i in a)print a[i]}' #初始化一个数组、并循环数组打印出来
echo "--------------"
awk -F: '{{a[NR]=$1}{print NR,a[NR];}}' /etc/passwd #按照分号切割/etc/passwd之后将第一列存入数组,然后打印出来
echo "--------------"
sed -n '29,34p' 7.example.txt
echo "--------------"
sed -n '29,34p' 7.example.txt|awk '{a[$1]+=$2}END{for(i in a){print i" "a[i]}}' #将相同key[第一列]后的value[第二列]值相加,
echo "--------------"
sed -n '29,34p' 7.example.txt|awk '{a[$1]+=$2}END{for(i in a){print i" "a[i]}}'|sort -nr -k 2 #将相同key[第一列]后的value[第二列]值相加,并按照第二列进行排序
#2.BEGIN,END,next的用法
>awk中两个特别的表达式 任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
echo "--------------"
cat /etc/passwd |awk 'BEGIN {FS=":";OFS="%"}{print $1,$5}' #先在BEGIN后的{}定义输入时的分隔符:和输出的分隔符%,然后再进行打印
echo "--------------"
cat /etc/passwd |awk 'BEGIN {FS=":";OFS="#"} gsub(/root/,"admin",$1) {print $0}'
#先定义输入分隔符:和输出分隔符#,然后在匹配第一列包含root,然后将第一列的root替换为admin
echo "--------------"
cat /etc/passwd |awk 'BEGIN {FS=":";OFS="#"} gsub(/root/,"admin") {print $1,$5}' #先定义输入分隔符:和输出分隔符#,然后在匹配全部包含root,然后将全部root替换为admin
echo "--------------"
sed -n '24,27p' 7.example.txt
echo "--------------"
sed -n '24,27p' 7.example.txt|awk '{N+=$1} END {print N}' #先进行累加,累加完之后在END之后进行打印
echo "--------------"
sed -n '36,38p' 7.example.txt
echo "--------------"
sed -n '36,38p' 7.example.txt|awk 'BEGIN { FS=":";OFS="\t";print "产品\t销售额";total=0} {print $1,$2;total=total+$2;} END {printf "总计\t%.2f\n",total}'
#第一步:先定义输入分隔符:输出分隔符\t。同时定义变量total=0,并打印"产品\t销售额"
#第二步:逐行打印并循环累加 {print $1,$2;total=total+$2;}
#第三步:执行完第二步之后打印结果:{printf "总计\t%.2f\n",total}
#3.next用法
awk '{if(NR==1){next} print $1,$2}' #next相当于循环中的continue,该语句的意思是当等于第一行时,就继续下一次循环,不打印,其余的就打印第一列、第二列。
#4.awk内置函数
echo "123" | awk '{print length}' #length 统计字符串长度
echo "123" | awk '{print substr($0,1,2)}' #substr 字符串切割从第N个字符开始往后M个字符substr(str,N,M)
#4.1system函数
awk 'BEGIN{b=system("ls -al");print b;}' #将执行命令的结果返回给b,并打印出来
#4.2sub,gsub喊出 字符串替换
echo "Linux Os2020 is Good system" | awk '{sub(/20/,"88",$2);print}' #将第二列第一次出现20替换成88
echo "Linux Os2020 is Good system" | awk '{gsub(/20/,"88",$2);print}' #将第二列全部出现的20替换成88
echo "Linux Os2020 is Good system"|awk '{gsub(/[0-9]+/,"",$0);print}' #将全部匹配的连续数字进行替换为空
echo "Linux Os2020 is Good system"|awk '{gsub(/[0-9]+/,"",$2);print}' #将第二列匹配的连续数字进行替换为空
#4.3 split喊出 字符串分隔返回一个数组
echo "15:32:43"| awk '{split($0,a,":");print a[1],a[2],a[3]}' #将字符串分隔并赋予数组a中。
#4.4 index喊出 字符串查找
awk 'BEGIN{info="shell is a good22 tools,so good!";print index(info,"good")}' #找到返回字符的位置12,否则返回0
awk 'BEGIN{info="shell is a good22 tools,so good!";print index(info,"good")?"yes":"no"}' #找到返回yes,否则返回no
#4.5match 正则表达式匹配查找
awk 'BEGIN{info="shell is a good2020 tools,so good!";print match(info,/[0-9]+/)}' #找到数字部分,返回字符的位置16,否则返回0
awk 'BEGIN{info="shell is a good2020 tools,so good!";print match(info,/[0-9]+/)?"yes":"no"}' #找到数字部分,找到返回yes,否则返回no
#4.6 systime函数 中strftime汗水 将时间戳转日期
awk 'BEGIN{print strftime("%Y-%m-%d",systime())}' #打印当前时间
echo "1435548542"|awk '{print strftime("%Y%m%d-%H%M%S",$1)}' #时间戳转时间
awk 'BEGIN {printf("%d\n",mktime(2006" "8" "5" "15" "09" "0))}' #将日期转为时间戳将06年8月15日转为时间戳
#4.7 asort,asorti排序函数
#【1】.asort 对value排序,不能保存key-value的关系
#【2】.asorti 对key排序,可以保存key-value的关系
sed -n '32,34p' 7.example.txt|awk '{a[$1]=$2}END{for(i in a) print i,a[i]}' #awk是关联数组。for…in循环输出时候,默认打印出来是无序数组
sed -n '32,34p' 7.example.txt|awk '{a[$1]=$2}END{slen=asort(a,b);for(i=1;i<=slen;i++) print i,a[i],b[i]}' #asort对a数组中的数字【value】进行排序然后存入b数组中,然后返回数组长度到slen,同时将a数组清空
sed -n '32,34p' 7.example.txt|awk '{a[$1]=$2}END{slen=asorti(a,b);for(i=1;i<=slen;i++) print i,b[i],a[b[i]]}'
#asorti对a数组中的字母【key】进行排序然后存入b数组中,然后返回数组长度到slen。再把数组b的值当作数组a的下标值打印数组a的值