描述awk命令和函數(shù)的用法及示例

一敢艰、簡(jiǎn)介

awk是一個(gè)強(qiáng)大的文本分析工具舵匾,相對(duì)于grep的查找俊抵,sed的編輯,awk在其對(duì)數(shù)據(jù)分析并生成報(bào)告時(shí)坐梯,顯得尤為強(qiáng)大徽诲。簡(jiǎn)單來說awk就是把文件逐行的讀入,以空格為默認(rèn)分隔符將每行切片吵血,切開的部分再進(jìn)行各種分析處理谎替。

awk有3個(gè)不同版本: awk、nawk和gawk践瓷,未作特別說明院喜,一般指gawk,gawk 是 AWK 的 GNU 版本晕翠。

二喷舀、命令的用法

命令格式

gawk [options] 'program...' FILE ...
?

常見選項(xiàng)

-F fs:指明字段分隔符;
-v var=value:自定義變量淋肾;

program語句

常見格式:PATTERN{ACTION STATEMENTS} #語句之間用分號(hào)分隔

  1. print
  • 逗號(hào)分隔符
  • 輸出的各item可以是字符串硫麻、數(shù)值、記錄的字段樊卓、變量或awk表達(dá)式
  • 省略item拿愧,打印全部字段,相當(dāng)于print $0碌尔。
  1. 變量
  • 內(nèi)建變量
    FS:輸入字段分隔符浇辜,默認(rèn)為空白字符;
    OFS:輸出字段分隔符唾戚,默認(rèn)為空白字符柳洋;
    RS:輸入時(shí)的換行符;
    ORS:輸出時(shí)的換行符叹坦;
    NF:每行的字段數(shù)熊镣,$NF表示最后一個(gè)字段;
    NR:表示行數(shù)募书;
    FNR:若提供多個(gè)文件绪囱,則分別計(jì)算各文件的行數(shù);
    FILENAME:當(dāng)前文件名莹捡;
    ARGC:命令行參數(shù)的個(gè)數(shù)鬼吵;
    ARGV:參數(shù)數(shù)組,保存的是命令行給定的各參數(shù)道盏;
  • 自定義變量
    (1) -v var=value #變量名區(qū)分字符大小寫而柑;
    (2) 在program中直接定義
  1. printf命令
  • 格式化輸出:printf FORMAT, item1, item2, ...
    (1) FORMAT必須給出;
    (2) 不會(huì)自動(dòng)換行文捶,需要顯式給出換行控制符荷逞,\n
    (3) FORMAT中需要分別為后面的每個(gè)item指定一個(gè)格式化符號(hào)媒咳;
  • 格式符:
    %c: 顯示字符的ASCII碼;
    %d, %i: 顯示十進(jìn)制整數(shù)种远;
    %e, %E: 科學(xué)計(jì)數(shù)法數(shù)值顯示涩澡;
    %f:顯示為浮點(diǎn)數(shù);
    %g, %G:以科學(xué)計(jì)數(shù)法或浮點(diǎn)形式顯示數(shù)值坠敷;
    %s:顯示字符串妙同;
    %u:無符號(hào)整數(shù);
    %%: 顯示%自身膝迎;
  • 修飾符:
    #[.#]:第一個(gè)數(shù)字控制顯示的寬度粥帚;第二個(gè)#表示小數(shù)點(diǎn)后的精度。 %3.1f
    -: 左對(duì)齊
    +:顯示數(shù)值的符號(hào)
  1. 操作符
    算術(shù)操作符: x+y, x-y, x*y, x/y, x^y, x%y限次,-x芒涡,+x
    字符串操作符:沒有符號(hào)的操作符,字符串連接
    賦值操作符:=, +=, -=, *=, /=, %=, ^=, ++, --
    比較操作符:>, >=, <, <=, !=, ==
    模式匹配符::是否匹配卖漫,!:是否不匹配
    邏輯操作符:&&费尽,||,!
    函數(shù)調(diào)用:function_name(argu1, argu2, ...)
    條件表達(dá)式:selector?if-true-expression:if-false-expression

  2. PATTERN
    (1) empty:空模式羊始,匹配每一行旱幼;
    (2) /regular expression/:僅處理能夠被此處的模式匹配到的行;
    (3) relational expression: 結(jié)果為真才會(huì)被處理突委;真為非0值柏卤,非空字符串;
    (4) line ranges:行范圍匀油,startline,endline:/pat1/,/pat2/
    注意: 不支持直接給出數(shù)字的格式
    ~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
    (5) BEGIN/END模式
    BEGIN{}: 僅在開始處理文件中的文本之前執(zhí)行一次缘缚;
    END{}:僅在文本處理完成之后執(zhí)行一次;

  3. 常用的action
    (1) Expressions
    (2) Control statements:if, while等钧唐;
    (3) Compound statements:組合語句忙灼;
    (4) input statements
    (5) output statements

  4. 控制語句

  • if(condition) {statments}
    if(condition) {statments} else {statements}
    while(conditon) {statments}
    do {statements} while(condition)
    for(expr1;expr2;expr3) {statements}
    break
    continue
    delete array[index]
    delete array
    exit
    { statements }

  • if-else:if(condition) statement [else statement]
    ~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
    ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
    ~]# awk '{if(NF>5) print $0}' /etc/fstab
    ~]# df -h | awk -F[%] '/^/dev/{print $1}' | awk '{if($NF>=20) print $1}'
    使用場(chǎng)景:對(duì)awk取得的整行或某個(gè)字段做條件判斷;

  • while:while(condition) statement
    條件“真”钝侠,進(jìn)入循環(huán)该园;條件“假”,退出循環(huán)帅韧;
    ~]# awk '/^[[:space:]]linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
    ~]# awk '/^[[:space:]]
    linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
    使用場(chǎng)景:對(duì)一行內(nèi)的多個(gè)字段逐一類似處理時(shí)使用里初;對(duì)數(shù)組中的各元素逐一處理時(shí)使用;

  • do-while:do statement while(condition)
    意義:至少執(zhí)行一次循環(huán)體

  • for:for(expr1;expr2;expr3) statement
    for(variable assignment;condition;iteration process) {for-body}
    ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg

    特殊用法:
    能夠遍歷數(shù)組中的元素忽舟;
    語法:for(var in array) {for-body}

  • switch
    switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}

  • break和continue
    break [n]
    continue

  • next
    提前結(jié)束對(duì)本行的處理而直接進(jìn)入下一行双妨;
    ~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

  • array

關(guān)聯(lián)數(shù)組:array[index-expression]
index-expression:
(1) 可使用任意字符串淮阐;字符串要使用雙引號(hào);
(2) 如果某數(shù)組元素事先不存在刁品,在引用時(shí)泣特,awk會(huì)自動(dòng)創(chuàng)建此元素,并將其值初始化為“空串”挑随;
若要判斷數(shù)組中是否存在某元素状您,要使用"index in array"格式進(jìn)行;
weekdays[mon]="Monday"
若要遍歷數(shù)組中的每個(gè)元素兜挨,要使用for循環(huán)膏孟;
for(var in array) {for-body}
~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
注意:var會(huì)遍歷array的每個(gè)索引;
如果數(shù)組不存在拌汇,我們引用數(shù)組柒桑,會(huì)創(chuàng)建,值為空噪舀,引用數(shù)組的值為0魁淳。

  • 函數(shù)

1.內(nèi)置函數(shù)
數(shù)值處理:
rand():返回0和1之間一個(gè)隨機(jī)數(shù)
字符串處理:
length([s]):返回指定字符串的長(zhǎng)度;
sub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內(nèi)容傅联,并將其第一次出現(xiàn)替換為s所表示的內(nèi)容先改;t中有沒有r,有替換成s
gsub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內(nèi)容蒸走,并將其所有出現(xiàn)均替換為s所表示的內(nèi)容仇奶;
split(s,a[,r]):以r為分隔符切割字符s,并將切割后的結(jié)果保存至a所表示的數(shù)組中比驻;
~]# netstat -tan | awk '/^tcp>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'

2.自定義函數(shù)

三该溯、入門實(shí)例

1.把文本分片后排列整齊,并加上標(biāo)簽
[root@localhost sctript]# cat awk01 
 Mike Harrington:(510) 548-1278:250:100:175
 Christian Dobbins:(408) 538-2358:155:90:201
 Susan Dalsass:(206) 654-6279:250:60:50
 Archie McNichol:(206) 548-1348:250:100:175
 Jody Savage:(206) 548-1278:15:188:150
 Guy Quigley:(916) 343-6410:250:100:175
 Dan Savage:(406) 298-7744:450:300:275
 Nancy McNeil:(206) 548-1278:250:80:75
 John Goldenrod:(916) 348-4278:250:100:175
 Chet Main:(510) 548-5258:50:95:135
 Tom Savage:(408) 926-3456:250:168:200
 Elizabeth Stachelin:(916) 440-1763:175:75:300
[root@localhost sctript]# awk -F: 'BEGIN{printf "%-20s %-15s %-4s %-4s %-4s\n","Name","PHone","Jan","Feb","MAR"}BEGIN{print"--------------------------------------------------"}{printf "%-20s %-15s %-4s %-4s %-4s\n",$1,$2,$3,$4,$5}' awk01
Name                 PHone           Jan  Feb  MAR 
--------------------------------------------------
 Mike Harrington     (510) 548-1278  250  100  175 
 Christian Dobbins   (408) 538-2358  155  90   201 
 Susan Dalsass       (206) 654-6279  250  60   50  
 Archie McNichol     (206) 548-1348  250  100  175 
 Jody Savage         (206) 548-1278  15   188  150 
 Guy Quigley         (916) 343-6410  250  100  175 
 Dan Savage          (406) 298-7744  450  300  275 
 Nancy McNeil        (206) 548-1278  250  80   75  
 John Goldenrod      (916) 348-4278  250  100  175 
 Chet Main           (510) 548-5258  50   95   135 
 Tom Savage          (408) 926-3456  250  168  200 
 Elizabeth Stachelin (916) 440-1763  175  75   300 
2.刪除行內(nèi)與第一列字符相同的字符
[root@localhost sctript]# cat c
a b c a d a
s d d d x s a
h j s a s h j h
j d f j a s j k j
[root@localhost sctript]# awk '{a=$1;gsub(" ?"a,"");print a""$0}' c
a b c d
s d d d x a
h j s a s j
j d f a s k

a=$1把第一列賦值變量a别惦。
gsub(" ?"a,"")用函數(shù)gsub進(jìn)行行內(nèi)全局替換狈茉," ?"a是正則,表示前面的空格可以沒有也可以有一次掸掸,把匹配到的全部替換成空格氯庆。
print a""$0打印,在行首添加上變量a扰付,也就字段$1堤撵。

3.打印學(xué)生的平均成績(jī)
[root@localhost sctript]# cat d
Sophia huaxue 90
Faye   huaxue 80
Sophia wuli   70
Faye   wuli   60
[root@localhost sctript]# awk '{b[$1]=$1} {a[$1]++;c[$1]+=$3} END {for(i in b);for(i in a);for(i in c){y=c[i]/a[i];printf("%-8s平均成績(jī)?yōu)?\t%2.2f\n",b[i],y)}}' d
Sophia  平均成績(jī)?yōu)?  80.00
Faye    平均成績(jī)?yōu)?  70.00

分析分兩步:
1.先打印名字
awk '{b[$1]=$1}END{for(i in b)print b[i]}' d
Sophia
Faye
{b[$1]=$1}以名字為變量b的下標(biāo),并在里面賦值名字羽莺。
END{for(i in b)print b[i]}在最后实昨,遍歷數(shù)組b,并打印每一個(gè)元素盐固。

2.打印平均分?jǐn)?shù)
]# awk '{a[$1]++;c[$1]+=$3}END{for(i in a){y=c[i]/a[i];print y}}' d
80
70
{a[$1]++;c[$1]+=$3}以名字為變量a的下標(biāo)荒给,自增計(jì)數(shù)丈挟。以名字為變量c的下標(biāo),拿自己和$3分?jǐn)?shù)的相加在賦值給自己志电。
{y=c[i]/a[i];print y}總分除以計(jì)數(shù)的到平均分

把兩個(gè)整合awk '{b[$1]=$1} {a[$1]++;c[$1]+=$3} END {for(i in b);for(i in a);for(i in c){y=c[i]/a[i];printf("%-8s平均成績(jī)?yōu)?\t%2.2f\n",b[i],y)}}' d

4.文本a記錄姓名曙咽、學(xué)號(hào),文本b記錄學(xué)號(hào)溪北、學(xué)科桐绒、成績(jī)夺脾。把a(bǔ)和b組合成一張表格之拨。
[root@localhost sctript]# cat a
Sophia|0001
Faye|0002

[root@localhost sctript]# cat b
0001|Chinese|77
0001|Music|90
0002|Chinese|62
0002|Music|80
[root@localhost sctript]# awk -F \| 'NR==FNR{a[$2]=$1;next}{printf "%-8s %-6s %-8s %-2s\n",a[$1],$1,$2,$3}' a b
Sophia   0001   Chinese  77
Sophia   0001   Music    90
Faye     0002   Chinese  62
Faye     0002   Music    80

NR表示a數(shù)據(jù)和b數(shù)據(jù)的總行數(shù),F(xiàn)NR表示a和b分別計(jì)數(shù)
NR==FNR為真時(shí)表示讀入的是a數(shù)據(jù)咧叭,執(zhí)行之后的代碼a[$2]=$1;next
a[$2]=$1;next表示把a(bǔ)文件切片的字段1放入數(shù)組a蚀乔,數(shù)組a下標(biāo)用字段2的值
NR==FNR為假時(shí)表示讀入的是b數(shù)據(jù),執(zhí)行printf中的代碼

printf "%-8s %-6s %-8s %-2s\n",a[$1],$1,$2,$3格式化輸出b文件切片后的值
a[$1],$1,$2,$3菲茬,其中第一個(gè)a[$1]是讀取a文件時(shí)新建的數(shù)組a吉挣,這是個(gè)關(guān)聯(lián)數(shù)組,文件a中$2的值等于文件b中$1的值婉弹,所以就可以把文件a存入數(shù)組的值和文件b的各字段數(shù)值一起打印出來睬魂。

5.把文本分片后按字母順序輸出相同兩個(gè)字符的字段
[root@localhost sctript]# cat sting 
asf|zz|123|bb|q23|cc|py|dd|ab|ee|x6|ff|ffq|gg|aaa|hh|aa
[root@localhost sctript]# awk -F \| '{for(i=1;i<=NF;i++){if($i~/^([a-z]){2}$/) {a=substr($i,1,1);b=substr($i,2,2);if(a==b) print $i | "sort"}}}' sting 
aa
bb
cc
dd
ee
ff
gg
hh
zz

文本切割后按照字段個(gè)數(shù)挨個(gè)循環(huán),用模式匹配出只有2個(gè)字母的字段镀赌,對(duì)這個(gè)字段的兩個(gè)字母對(duì)比氯哮,相等時(shí)打印并傳遞到sort命令中排序。

6.把grades中每行的字段分別從小到大排序
[root@localhost sctript]# cat grades 
44 55 66 22 77 99
100 22 77 99 33 66
55 66 100 99 88 45
[root@localhost sctript]# vim sorter.awk 
#!/bin/awk -f
#這里我用選擇排序算法進(jìn)行排序
{for(i=0;i<NF;i++){array[i]=$(i+1)}}
sort(array)

function sort (temp){
        for(i=0;i<length(temp)-1;i++){
                min=i
                for(j=i+1;j<length(temp);j++){
                        if(temp[min]>temp[j]){
                                min=j
                        }
                }
                if(min!=i){
                        temp1=temp[i]
                        temp[i]=temp[min]
                        temp[min]=temp1
                }
        }
        for(i=0;i<NF;i++){
                printf("%d ", temp[i])
        }
        printf "\n"
}
[root@localhost sctript]# ./sorter.awk grades
22 44 55 66 77 99 
22 33 66 77 99 100 
45 55 66 88 99 100
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末商佛,一起剝皮案震驚了整個(gè)濱河市喉钢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌良姆,老刑警劉巖肠虽,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異玛追,居然都是意外死亡税课,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門痊剖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來韩玩,“玉大人,你說我怎么就攤上這事邢笙⌒ト纾” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵氮惯,是天一觀的道長(zhǎng)叮雳。 經(jīng)常有香客問我想暗,道長(zhǎng),這世上最難降的妖魔是什么帘不? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任说莫,我火速辦了婚禮,結(jié)果婚禮上寞焙,老公的妹妹穿的比我還像新娘储狭。我一直安慰自己,他們只是感情好捣郊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布辽狈。 她就那樣靜靜地躺著,像睡著了一般呛牲。 火紅的嫁衣襯著肌膚如雪刮萌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天娘扩,我揣著相機(jī)與錄音着茸,去河邊找鬼。 笑死琐旁,一個(gè)胖子當(dāng)著我的面吹牛涮阔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灰殴,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼敬特,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了验懊?” 一聲冷哼從身側(cè)響起擅羞,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎义图,沒想到半個(gè)月后减俏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碱工,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年娃承,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怕篷。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡历筝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出廊谓,到底是詐尸還是另有隱情梳猪,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布蒸痹,位于F島的核電站春弥,受9級(jí)特大地震影響呛哟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匿沛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一扫责、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逃呼,春花似錦鳖孤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蔫缸,卻和暖如春腿准,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拾碌。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留街望,地道東北人校翔。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像灾前,于是被迫代替她去往敵國(guó)和親防症。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Linux指令中文說明傳送入口 整理自Linux指令中文說明 文本和數(shù)據(jù)進(jìn)行處理的編程語言awk 是一種編程語言哎甲,...
    釋閑人閱讀 2,125評(píng)論 1 6
  • awk介紹awk變量printf命令:實(shí)現(xiàn)格式化輸出操作符awk patternawk actionawk數(shù)組aw...
    哈嘍別樣閱讀 1,567評(píng)論 0 4
  • awk: grep,sed,awk grep:文本過濾 sed:文本編輯 awk:文本格式化工具蔫敲; 1 什么是aw...
    木林森閱讀 1,784評(píng)論 0 16
  • 本章主要學(xué)習(xí)內(nèi)容awk介紹 ?awk基本用法 ?awk變量 ?awk格式化 ?awk操作符 ?awk條件判斷 ?a...
    楠人幫閱讀 1,271評(píng)論 0 8
  • 元旦放假三天,帶著兒子去了佛山探望弟弟一家和媽媽炭玫。本來是因?yàn)榘职指艿芩麄兓乩霞胰ジ惴课莸鼗チ四魏伲瑡寢屢粋€(gè)人要帶四...
    甜小丫的芳草園閱讀 368評(píng)論 2 1