LINUX 三剑客之awk
一 概述
AWK是一種處理文本文件的語言,是一個強大的文本分析工具。它是專門為文本處理設計的編程語言,也是行處理軟件,通常用于掃描、過濾、統(tǒng)計匯總工作數(shù)量,可以來自標準輸入也可以是管道或文件
20世紀70年代誕生于貝爾實驗室,現(xiàn)在centos7用的是gawk,之所以叫AWK是因為其取了三位創(chuàng)始人Alfred Aho,Peter Weinberger,和l Brian Kernighan 的 Family Name 的首字符。
工作原理:
當讀到第一行時,匹配條件,然后執(zhí)行指定動作,再接著讀取第二行數(shù)據(jù)處理,不會默認輸出,如果沒有定義匹配條件默認是匹配所有數(shù)據(jù)行,awk隱含循環(huán),條件匹配多少次動作就會執(zhí)行多少次。
工作原理:
逐行讀取文木,默認以空格或tab鍵為分隔符進行分隔,將分隔所得的各個字段保存到內(nèi)建變量中,并按模式或者條件執(zhí)行編輯命令。
sed命令常用于一整行的處理,而awk比較傾向于將一行分成多個""字段"然后再進行處理。.awk信息的讀入也是逐行讀取的,執(zhí)行結(jié)果可以通過print的功能將字段數(shù)據(jù)打印顯示。在使用awk命令的過程中,可以使用邏輯操作符"&&"表示"與"、"||表示"或"、"!"表示非" ;還可以進行簡單的數(shù)學運算,如+、-、*、/、%、^分別表示加、減、乘、除、取余和次方。
命令格式:
awk選項·模式或條件操作 ?文件1文件2
awk?-f腳本文件 ?文件1?文件2 --
格式: awk?關鍵字?選項 ?命令?部分’{xxxx}'文件名
RS:行分隔符。awk從文件上讀取資料時,將根據(jù)RS的定義把資料切割成許多條記錄,而awk一次僅讀入一條記錄,以進行處理。預設值是"\n'
簡說:數(shù)據(jù)記錄分隔,默認為\n,即每行為一條記錄
練習
awk '{print}' lianxi.txt 打印所有
[root@localhost home]# awk '{print $1}' lianxi.txt ?#打印第一列
?//awk默認把這一行當做一列,因為沒有被空格分隔,awk默認以空格或tab鍵分隔
[root@localhost home]# awk -F: '{print $1}' lianxi.txt
//定義冒號為分隔符顯示分隔之后的第1列
[root@localhost ~]# awk -Fx '{print $1}'?/etc/passwd ? ??用x作為分隔符
root :
$1與$2 之間的逗號代表空格
將空格用雙引號括起來也可以顯示出空格來,沒有空格只能當做一個正常變量
\t 表示制表符。也是tab鍵。
[root@localhost home]# awk -F[:/] '{print $1,$2}' lianxi.txt
#定義兩個分隔符,:或者/ 兩個有其中一個都算作是分隔符
NF ?FS ?NR ?$0 ?$n ?RS的使用舉例
$1:代表第一列
$2:代表第二列以此類推
$0:代表整行
NF:一行的列數(shù)
NR:行數(shù)
[rootelocalhost ~]# awk ?' /root/{print $0}" pass.txt ?#打印包含root的整行內(nèi)容
root: x:0:o : root: /root: /bin/ bash
[root@localhost~]#awk -F: " /root/ {print $1}?' pass.txt ??#打印包含root的行的第一列
root
[root@localhost ~]# awk -F: '/root/{print $1,$6}' pass.txt
//打印包含root的行的第一列和第六列
root /root
[root@localhost home]# awk -F: '/\!/{print $1}' /etc/shadow
輸出shadow文件中以冒號分隔的第二列有感嘆號的行的第一列
[root@localhost ~]# awk -F[ :/] '{print NF}' ?zz ? ?
//打印zz文件每一行以:分割的列數(shù)
[root@localhost home]# awk -F: '{print NF,$0}' lianxi.txt
//打印lianix.txt文件每一行以:分割的列數(shù)及每行的內(nèi)容
[root@localhost home]# awk -F: '{print $NF}' lianxi.txt
//打印lianix.txt文件每一行以:分割的最后一列
[root@localhost home]# awk ?‘{print NR}'?lianxi.txt ? ??只顯示每一行行號
[root@localhost home]# awk '{print NR,$0}' lianxi.txt ? ?顯示每一行的行號及每一行的內(nèi)容
[root@localhost ~]# awk 'END{print NR}' ?/etc/passwd ? ? ?//打印總行數(shù)
[root@localhost ~]# awk 'END{print $0 }'?/etc/passwd ??//打印文件最后一行
[root@localhost ~]# awk?-F:?‘{print "當前行有"NF"列"}’ ?zz?打印當前行以:分割的總共有幾列
[root@localhost ~]# awk -F: '{print "第"NR"行有"NF"列" }'/etc/passwd ? ??//第幾行有幾列
擴展生產(chǎn):網(wǎng)卡的ip、流量
[rootelocalhost ~j# ifconfig ens33 | awk ' /netmask/{print "本機的ip地址是"$2}'
本機的ip地址是192.168.245.211
[root@localhost ~]# ifconfig ens33 | awk '/RX p/{print $5"字節(jié)"}’
8341053字節(jié)
根分區(qū)的可用量
[ rot@localhost ~]# df -h l awk 'NR==2{print $4 }'
52G
逐行執(zhí)行開始之前執(zhí)行什么任務,結(jié)束之后再執(zhí)行什么任務,用BEGIN、END
BEGIN一般用來做初始化操作,僅在讀取數(shù)據(jù)記錄之前執(zhí)行一次
END一般用來做匯總操作,僅在讀取完數(shù)據(jù)記錄之后執(zhí)行一次
awk的運算:
[root@localhost ~]# awk 'BEGIN{x=10;print x}’
//如果不用引號awk就當作一個變量來輸出了,所以不需要加$了
[root@localhost ~]# awk 'BEGIN{x=10;print x+1}'
//BEGIN在處理文件之前,所以后面不跟文件名也不影響
[ rootelocalhost~]#awk 'BEGIN{x=10;x++; print x}'
[ root@localhost ~]# awk 'BEGIN{print x+1}’
//不指定初始值,初始值就為0,如果是字符串,則默認為空
[root@localhost ~]# awk 'BEGIN{print 2.5+3.5}'
//小數(shù)也可以運算
[ rootelocalhost~]#awk 'BEGIN{?print 2-1}"
[ rootelocalhost ~]#awk "BEGIN{print 3*4 } "
[ rootelocalhost~].awk 'BEGIN{ print 3**2}'9
[root@localhost ~]# awk 'BEGIN{print 2^3}' ? ?^和**都是冪運算
[ rootelocalhost~]#awk 'BEGIN{print 1/2}" ?0.5
模糊匹配,用~表示包含,!~表示不包含
[rootelocalhost ~]"awk -F:?'$1~/root/' /etc/passwd ?文件中以:分割的第一列包含root的
[root@localhost ~]# awk -F:?'$1~/ro/' /etc/passwd ?//模糊匹配,只要有ro就匹配上
[root@8localhost ~]# awk -F:?'$7!~/nologin$/{print $1,$7}" /etc/passwd ?
文件中以:分割的第7列不包含nologin的 第一列和第七列打印出來
關于數(shù)值與字符串的比較
比較符號: ?= ?!= ??=> ?<= ?> ?<
[rootelocalhost ~] # awk ?'NR==5{print}?‘ ?/etc/passwd ?打印文件第5行
[rootelocalhost ~] # awk ?'NR<5{print}?‘ ?/etc/passwd ?
打印文件小于第5行的,1-4行
[ rootelocalhost~]#awk -F:"$3==0' /etc/passwd
[root8localhost ~]#awk -F: '$1=-root' /etc/passwd
[root@localhost ~j# awk -F: '$1=="root"' /etc/passwd
//精確匹配一定是root
[ rootelocalhost ~ ]# awk -F: "$3>=1000' /etc/passwd
邏輯運算 ?
&& ?ll
[root@localhost ~]#awk -F: '$3<10 ||?$3>=1000'?/etc/passwd
[root@localhost ~j#awk -F: '$3>10 && $3<1000'?/etc/passwd ?
[root@localhost ~]# awk -F: 'NR>4 && NR<10'?/etc/passwd
案列:
打印1-200之間所有能被7整除并且包含數(shù)字7的整數(shù)數(shù)字
[ rootelocalhost ~] seq 200 |awk '$1%7==0 && $1~/7/’
70
77
147
175
其他內(nèi)置變量的用法FS、OFS、NR、FNR、RS、ORS
[root@localhost~]# awk 'BEGIN{FS=": "}?{print $1}' pass.txt
//在打印之前定義字段分隔符為冒號 ?等于 awk -F: ?‘{print $1}’?pass.txt
[ rootelocalhost ~]# awk 'BEGIN{FS=": ";OFS="---"}?{print $1,$2}' pass.txt
//OFS定義了輸出時以什么分隔,$1$2中間要用逗號分隔,因為逗號默認被映射為OFS變量,而這個變量默認是空格
root---x
bin---x
daemon---x
adm---x
lp---x
[root@localhost ~]# awk '{print FNR,$0}' /etc/resolv.conf ?/etc/hosts
//可以看出FNR的行號在追加當有多個文件時
1
2nameserver 114.114.114.1143 search localdomain
1?127.0.0.l~ localhost localhost.localdomain localhost4 localhost4.localdomain4
2?i:llocalhost localhost.localdomain localhost6 localhost6.localdomain6
[root@localhost ~]# awk '{print NR,$0} '/etc/resolv.conf /etc/hosts
1
2nameserver 114.114.114.114
3?search localdomain
4127.0.0.l~ localhost localhost.localdomain localhost4 localhost4.localdomain4
5?::1localhost localhost.localdomain localhost6 localhost6.localdomain6
[rootelocalhost ~]# awk 'BEGIN{RS=":"{print $0}'?/etc/passwd
//RS;指定以什么為換行符,這里指定是冒號,你指定的肯定是原文里存在的字符
root
X
0
0
root
[root8localhost ~]#awk ?'BEGIN{ORS=?" "} {print $0}' /etc/passwd
ORS把多行合并成一行輸出,輸出的時候自定義以空格分隔每行,本來默認的是回車鍵
awk高級用法
定義引用變量
[ root@localhost ~]#a=100
[ rootelocalhost ~]# awk -v b="$a”?'BEGIN{print b}’
//將系統(tǒng)的變量a,在awk里賦值為變量b,然后調(diào)用變量b
100
[root@localhost ~]# awk 'BEGIN{print "'$a'"}’
//直接調(diào)用的話需要先用雙引號再用單引號
100
[rootelocalhost ~]# awk -vc=1 'BEGIN{print c}'
/ /awk直接定義變量并引用
調(diào)用函數(shù)getline,讀取一行數(shù)據(jù)的時候并不是得到當前行而是當前行的下一行
當getline左右無重定向符"<"或"I"時,awk首先讀取到了第一行,就是1,然后getline,就得到了1下面的第二行,就是2,因為getline之后,awk會改變對應的NE,NR,FNR和%0等內(nèi)部變量,所以此時的$0的值就不再是1,而是2了,然后將它打印出來。當getline左石有重定向符"<"或""I"時,getline則作用于定向輸入文件,由于該文件是剛打開,
并沒有被awk讀入一行,只是getline讀入,那么getline返回的是該文件的第一行,而不是隔行。
[root@localhost ~]# df -h / awk 'BEGIN{getline}/root/{print $0 }'
/ dev/mapper/centos-root ??50G ? ?5.2G ??45G ? ?11%/
[root@localhost ~]# seq 10 | awk ' { getline;print $0}' ??//顯示偶數(shù)行
2
4
6
8
10
[ root@localhost ~]# seq 10 | awk '{print $0;getline)'//顯示奇數(shù)行
1
3
5
7
if語句:awk的if語句也分為單分支、雙分支和多分支
單分支為if?(){ }
雙分支為if?(){ }else{?}
多分支為if?(){ }else?if?(){ }else{ }
[root@localhost ~]# awk -F: '{if($3<10){print $0}}'?/etc/passwd //第三列小于10的打印整行[root@localhost ~]# awk -F: '(if($3<10)(print $3}else{print $1}} '/etc/passwd
//第三列小于10的打印第三列,否則打印第一列
awk還支持for循環(huán)、while循環(huán)、函數(shù)、數(shù)組等其他
awk 'BEGIN{x=0};/\/bin\/bash$/{x++;print x,$0};END{print x}' /etc/passwd
統(tǒng)計以/ bin/ bash結(jié)尾的行數(shù),等同于grep -c ?"/bin/bash"?/etc/passwd
BEGIN模式表示,在處理指定的文木之前,需要先執(zhí)行BEGIN模式中指定的動作;awk再處理指定的文木,之后再執(zhí)行END模式中指定的動作,END{}語句塊中,往往會放入打印結(jié)果等語句
awk -F ":" '!($3<200){print}' /etc/passwd ??#輸出第3個字段的值不小于200的行
awk 'BEGIN{FS=":"};{if($3>=1000){print}}' /etc/passwd
先處理完BEGIN的內(nèi)容,再打印文木里面的內(nèi)容
awk -F":" '{max=($3>=$4) ??$3:$4; {print max)}}'?/etc/passwd(了解)
($3>$4)??$3:$4三元運算符,如果第3個字段的值大于等于第4個字段的值,則把第3個字段的值賦給max,否則第4個字段的值賦給max.
awk -F ":” ' (print NR,$0 )' /etc/passwd #輸出每行內(nèi)容和行號,每處理完一條記錄NR值加1
sed -n '=;P' /etc/passwd
awk -F ":"?'$7~"bash"{print ?$1,$7}'?/etc/passwcd
#輸出以冒號分隔且第7個字段中包含/bash的行的第1個字段
awrk -F: ?‘/ bash/{print ?$1}"?/etc/passwed
awk -F":"?"($1~"root") &&(NF==7){print $1,$2,$NF} ' /etc/passwd
第1個字段中包含root且有7個字段的行的第1、2個字段
awk -F ":"?"($7!="/bin/bash") & &($7!="/sbin/nologin") {print} '?/etc/passwd
輸出第7個字段既不為/bin/bash,也不為/sbin/nologin的所有行
awk -F:?'($NF !="/bin/bash")&&($NF !=”/sbin/nologin" ) {print NR,$0 }' passwd
通過管道、雙引號調(diào)用shell 命令:
Echo?$PATH | awk 'BEGIN{RS=":"};END {print NR}’
#統(tǒng)計以冒號分隔的文本段落數(shù),END語句塊中,往往會放入打印結(jié)果等語句
echo $PATH|awk 'BEGIN{RS=":"};{print NR,$0};END{print NR}'
awk -F: '/bash$/{print | "wc -l")' /etc/passwd
#調(diào)用wc -l命令統(tǒng)計使用bash 的用戶個數(shù),
#等同于grep -c "bash$" /etc/passwd
awk -F: ‘/ bash$/ {print}' pasawd l wc -l
查看內(nèi)存
free -m l awk '/Mem:/ {print int($3/($3+$4)*100)"%")′
查看當前內(nèi)存使用百分比
# free -m / awk ' /Mem:/ {print $3/$2)'
[root@localhost ~]# free -m|awk ‘/Mem:/ {print $3/$2*100}'
free -m | awk '/Mem:/{print $3/$2*100}' | awk -F. '{print $1"%"}'
比較后取整
查看CPU利用率
top -b -n 1 l grep Cpu | awk -F, ?{print $4}' l awk '{print $1}′
#查看當前cPv空閑率,(-b -n1表示只需要1次的輸出結(jié)果)
查看時間
last 是你關機或充氣的記錄,last | tail -1 是最后一次關機或重啟的時間;
開機時間記錄在/proc/uptime中可用
date -d "$(awk -F. '{print $1}' /proc/uptime) second ago" +"%Y-%m-%d %H:%M:%S"
來查看開機時間,和運行時間。(+號前面有空格)
awk 'BEGIN {n=0; while ("w" | getline) n++ ; {print n-2}}'
#調(diào)用w命令,并用來統(tǒng)計在線用戶數(shù)
awk 'BEGIN {?"hostname" l getline ; {print $0}}?'
調(diào)用hostname,并輸出當前的主機名
CPu使用率
cpu_us=`top -b -n 1 l grep Cpu | awk '{ print $2}`
cpu_sy=`top -b -n 1 | grep Cpu | awk -F, '{print $2}' | awk '{print $1}'`
cpu_sum=$ (($cpu_us+$cpu_sy))
echo $cpu_sum
?
echo "A B C D" l awk '{OFS="I"; print $0;$1=$1 ;print $0} '
$1-$1是用來激活$0的重新賦值,也就是說字段$1...和字段數(shù)NF的改變會促便awk重新計算$0的值,通常是在改變OFS后而需要輸出$0時這樣做
Awk?‘BEGIN{a[0]=10;a[1]=20; print a[1]}’
Awk?’BEGIN{a[o]=10;a[1]=20; print a[o]}"
Awk?'BEGIN{a[ "abc"]=10; a["xyz"]=20;print a ["abc"]}'
awk 'BEGINia [ "abc"]=10;a ["xyz"]=20; print a["xyz"]}’
awk 'BEGIN{a ["abe"]="aabbcc"; a["xyz"]="xyyzz" ; print a ["xyz"]}'
awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a){print i,a[i]}}’
PS1:BEGIN中的命令只執(zhí)行一次
PS2: awk數(shù)組的下標除了可以使用數(shù)字,也可以使用字符串,字符串需要使用雙引號
使用awk統(tǒng)計httpd訪問日志中每個客戶端IP的出現(xiàn)次數(shù)
awk '(ip[$1]++);END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log
備注:定義數(shù)組,數(shù)組名稱為ip,數(shù)字的下標為日怎文件的第1列(也就是客戶A的i?地址),+t的目的在于對客戶端進行統(tǒng)計計數(shù),客戶端IP出現(xiàn)―次計數(shù)器就加i。END中的指令在讀取完文件后執(zhí)行,通過循環(huán)將所有統(tǒng)計信息輸出,for循環(huán)遍歷的是數(shù)組名ip的下標。
awk '/Failed password/ {print $0}' /var/log/secure
awk '/Failed password/ {print $1}'?/var/log/secure
awk '/Failed/?{ip[$11]++};END{for(i in ip){print i”,”ip[i]}}' /var/log/secure
腳本編寫
#!/bin/ bash
x='awk?'/Failed password/{ip[$11]++};END{for(i in ip) (print i","ip[i]}}’/var/log/secure'
#190.168.80.13?3
for j in $x
do
ip= "echo $j l?awk -F ", " '{print $1}"
num="echo $j?l?awk -F ", " '{print $2}?"
if[ $num -ge 3 ];then
echo“警告$ip訪問本機失敗了$num次,請速速處理!”
fi
done
總結(jié)
以上是生活随笔為你收集整理的LINUX 三剑客之awk的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iptables 防火墙
- 下一篇: 账号安全控制