Linux基礎(chǔ)教程之文本三劍客AWK
文本三劍客—-awk(3)
awk簡(jiǎn)介
awk是一個(gè)強(qiáng)大的文本分析工具,與grep(查找)、sed(編輯)一并稱為“文本處理三劍客”。awk最強(qiáng)大的功能是對(duì)數(shù)據(jù)分析并生成報(bào)告。
awk有3個(gè)不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk是AWK的GNU版本。
awk其名稱得自于它的創(chuàng)始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個(gè)字母。awk能讀取輸入文件、為數(shù)據(jù)排序、處理數(shù)據(jù)、對(duì)輸入執(zhí)行計(jì)算以及生成報(bào)表,還有無數(shù)其他的功能。
工作原理
一次讀取一行文本,按輸入分隔符進(jìn)行切片,切成多個(gè)組成部分,將每片直接保存在內(nèi)建的變量中,$1,$2,$3….,引用指定的變量,可以顯示指定斷,或者多個(gè)斷。如果需要顯示全部的,需要使用$0來引用??梢詫?duì)單個(gè)片斷進(jìn)行判斷,也可以對(duì)所有斷進(jìn)行循環(huán)判斷。其默認(rèn)分隔符為空格
- 按行讀取文本(文件的每一行稱為記錄)
- 按輸入分隔符進(jìn)行切片
- 對(duì)切片自動(dòng)生命變量 $1,$2…(域標(biāo)識(shí);$0為所有域)
- 對(duì)指定目標(biāo)做處理(處理及打印等)
語法格式
awk [options] ‘program’ FILE……
[options]
–F:指明輸入時(shí)的分隔符
–v:自定義變量
–f:調(diào)用awk腳本
program:pattern{action statements;..}
-pattern:觸發(fā)條件
-action statements:對(duì)數(shù)據(jù)處理動(dòng)作
步驟
- 執(zhí)行BEGIN{action;…}
BEGIN在輸入之前執(zhí)行,通常用來打印表頭,變量初始化。 - 讀取,執(zhí)行pattern{action;…}
默認(rèn)執(zhí)行{ print } - 執(zhí)行END{action;…}
讀取到打印結(jié)束后執(zhí)行,通常用作分析結(jié)果,信息匯總。
變量
內(nèi)置變量
- FS:輸入字段分隔符
- OFS:輸出字段分隔符
- RS:輸入記錄分隔符
- ORS:輸出記錄分隔符
- ARGC:命令行參數(shù)的個(gè)數(shù)
- ARGV:數(shù)組,保存命令行給定的各參數(shù)
- NF:字段數(shù)量
- NR:行號(hào)
- FNR:個(gè)文件分別計(jì)數(shù),行號(hào)
- FILENAME:當(dāng)前文件名
自定義變量
- 選項(xiàng)位置定義:-v var=hello
- 在program中定義:awk ‘BEGIN{test=”hello”;print test}’
字符串處理
- length([s]) :返回指定字符串的長(zhǎng)度
- sub(r,s,[t]) :對(duì)t字符串進(jìn)行搜索r 表示的模式匹配的內(nèi)容,并將第一個(gè)匹配的內(nèi)容替換為s
echo “2008:08:08 08:08:08″ | awk ‘sub(/:/,”-“,$0)’ - gsub(r,s,[t]) :對(duì)t字符串進(jìn)行搜索r表示的模式匹配的內(nèi)容,并全部替換為s所表示的內(nèi)容
echo “2008:08:08 08:08:08″ | awk ‘gsub(/:/,”-“,$0)’ - split(s,array,[r]) :以r為分隔符,切割字符串s,并將切割后的結(jié)果保存至array 所表示的數(shù)組中,第一個(gè)索引值為1, 第二個(gè)索引值為2,…
netstat -tan | awk ‘/^tcp>/{split($5,ip,”:”);count[ip[1]]++} END{for (i in count) {print i,count[i]}}’
Printf命令
- print不需要指定,printf需要指定format
- printf后面的字串需要使用雙引號(hào)
- 字串定義后的內(nèi)容需要使用”,”分隔,后面直接跟Item1,item2….
- format用于指定后面的每個(gè)item的輸出格式
- printf語句不會(huì)自動(dòng)打印換行符\n
格式符
- %s: 顯示字符串
- %d,%i: 顯示十進(jìn)制整數(shù)
- %e,%E: 科學(xué)計(jì)數(shù)法數(shù)值顯示
- %f: 顯示為浮點(diǎn)數(shù)
- %g,%G: 以科學(xué)數(shù)法或浮點(diǎn)形式顯示數(shù)值
- %c: 顯示字符的ASCII碼
- %u: 無符號(hào)整數(shù)
- %%: 顯示%號(hào)自身,相當(dāng)于轉(zhuǎn)義
修飾符
- N: 顯示寬度
- -: 左對(duì)齊(默認(rèn)為右對(duì)齊)
- +: 顯示數(shù)值符號(hào)
操作符
- 算數(shù)
x+y, x-y, x*y, x/y, x^y, x%y - 賦值
=, +=, -=, *=, /=, %=, ^=,++, — - 比較
==, !=, >, >=, <, <= - 模式匹配符
~:左邊是否和右邊匹配包含!~:是否不匹配 - 邏輯
&&,||,!
awk -F: ‘{printf “Username: %-15s,UID:%d\n”,$1,$3}’ /etc/passwd
PROGRAM
pattern
- )默認(rèn)匹配每一行
- )/pattern/:僅處理匹配到的行
- )/pattern1/,/pattern2/:處理 pattern1 到 pattern2 之間
- )關(guān)系表達(dá)式:真:非0假:空或0
action
- )Expressions: 算術(shù),比較表達(dá)式等
- ) Control statements :if, while等
- ) Compound statements :組合語句
- ) input statements
- ) output statements :print等
控制語句
- if-else
awk ‘BEGIN{ test=100;if(test>90){print “very good”} else if(test>60){ print “good”}else{print “no pass”}}’
成績(jī)?yōu)?00;大于90打印“very good”;大于60打印“good”;其余打印“no pass” - while 循環(huán)
條件”真”,進(jìn)入循環(huán);條件”假”,退出循環(huán)
awk ‘/^[[:space:]]*Linux16/{i=1;while(i<=NF) {if(length($i)>=10){print $i,length($i)}; i++}}’ /etc/grub2.cfg
以空白符開頭后跟”Linux16″的行中,把字符數(shù)大于10的字符串打印出來。 - do-while 循環(huán)
無論真假,至少執(zhí)行一次
awk ‘BEGIN{ sum=0;i=0;do{sum+=i;i++;}while(i<=100);print sum}’
累加 - for 循環(huán)
遍歷
awk ‘/^[[:space:]]*Linux16/{for(i=1;i<=NF;i++) {print$i,length($i)}}’ /etc/grub2.cfg - switch 語句
- break 和 continue
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}’
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}’ - next
提前 結(jié)束對(duì)本行處理而直接進(jìn)入下一行處理
seq {1,20} | awk -F: ‘{if($1%2==0)next ; print $1}’
打印奇數(shù)行
數(shù)組
- )可使用任意字符串;字符串要使用雙引號(hào)括起來
- )如果某數(shù)組元素事先不存在,在引用時(shí),awk 會(huì)自動(dòng)創(chuàng)建此元素,并將其值初始化為“空字符串(即為”假”)”
- 若要判斷數(shù)組中是否存在某元素,要使用“index in array”格式進(jìn)行遍歷
示例練習(xí):
[root@localhost ~]# awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd root /bin/bash wang /bin/bash lao /bin/bash cai /bin/bash
[root@localhost ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd root /bin/bash wang /bin/bash lao /bin/bash cai /bin/bash
[root@localhost ~]# cat f aa bb cc dd aa bb cc dd [root@localhost ~]# awk '!arr[$0]++' f aa bb cc dd [root@localhost ~]# awk '{!arr[$0]++;print $0,arr[$0]}' f aa 1 bb 1 cc 1 dd 1 aa 2 bb 2 cc 2 dd 2
[root@localhost ~]# awk '/^UUID/||/^\/dev/{fs[$3]++} END{for (i in fs){print i,fs[i]}}' /etc/fstab swap 1 xfs 4
[root@localhost ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab man 1 and/or 1 maintained 1 xfs 4 Accessible 1 Thu 1 UUID=63af8e82-3a2a-40ed-8f76-64f56502ee1c 1are 1 defaults 4 blkid(8) 1 / 1 /dev/mapper/cl-root 1 0 10
[root@localhost ~]# echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw" | awk -F "[^[:digit:]]" '{for(k=1;k<=NF;k++){a[$k]}} END{for(i in a) {printf "%s",i}printf "\n"}' 79053