M25_第九周:awk

[TOC]

AWK介紹

awk是一個強大的文本分析工具,相對于grep的查找,sed的編輯,awk在其對數(shù)據(jù)分析并生成報告時,顯得尤為強大。簡單來說awk就是把文件逐行的讀入,以空格為默認(rèn)分隔符將每行切片,切開的部分再進行各種分析處理。

awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名稱得自于它的創(chuàng)始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有自己的語言: AWK 程序設(shè)計語言 , 三位創(chuàng)建者已將它正式定義為“樣式掃描和處理語言”。它允許您創(chuàng)建簡短的程序,這些程序讀取輸入文件、為數(shù)據(jù)排序、處理數(shù)據(jù)、對輸入執(zhí)行計算以及生成報表,還有無數(shù)其他的功能。

AWK工作原理

第一步:執(zhí)行BEGIN{action;... }語句塊中的語句
第二步:從文件或標(biāo)準(zhǔn)輸入(stdin)讀取一行,然后執(zhí)行pattern{ action;... }語句塊,它逐行掃描文件,從第一行到最后一行重復(fù)這個過程,直到文件全部被讀取完畢。
第三步:當(dāng)讀至輸入流末尾時,執(zhí)行END{action;...}語句塊BEGIN語句塊在awk開始從輸入流中讀取行之前被執(zhí)行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通??梢詫懺贐EGIN語句塊中END
語句塊在awk從輸入流中讀取完所有的行之后即被執(zhí)行,比如打印所有行的分析結(jié)果這類信息匯總都是在END
語句塊中完成,它也是一個可選語句塊pattern語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供
pattern語句塊,則默認(rèn)執(zhí)行{ print },即打印每一個讀取到的行,awk讀取的每一行都會執(zhí)行該語句塊

使用方法

基本格式:awk [options] 'program' file...

program:pattern {action statements;..}

pattern和action:

BEGIN,END
action statements對數(shù)據(jù)進行處理,放在{}內(nèi)指明
print,printf

分割符、域和記錄

awk執(zhí)行時,由分隔符分隔的字段(域)標(biāo)記$1,$2..$n稱為域標(biāo)識。$0為所有域,注意:和shell中變量$符含義不同
文件的每一行稱為記錄
省略action,則默認(rèn)執(zhí)行print $0 的操作

格式和變量

print格式:

print item1, item2, ...
要點
(1) 逗號分隔符
(2) 輸出的各item可以字符串,也可以是數(shù)值;當(dāng)前記錄的字段、變量或awk的表達(dá)式
(3) 如省略item,相當(dāng)于print $0

awk內(nèi)置變量:

FS或-F:輸入字段分隔符,默認(rèn)為空白字符

FS實例:
[ root@CentOS ~]#awk    '{print $1}' score.txt    
mage
wang
zhang
li
---------------------------------------------------------------
[ root@CentOS ~]#awk  -v FS=':' '{print $1,$3}' score2.txt 
mage male
wang male
zhang female
li female
[ root@CentOS ~]#cat score2.txt 
mage:100:male
wang:90:male
zhang:80:female
li:100:female
//-v FS=":"以":"分割符,取出文本中的$1(第一列)、$3(第三列)。注意:分割符(":")必須是文本中內(nèi)容有的,如果文中沒有 ":"是沒有結(jié)果的,如下:
[ root@CentOS ~]#awk -v FS=":" '{print $1,$3}' score.txt          
mage 100 male 
wang 90 male 
zhang 80 female 
li 100 female
//他就會打印全部
-F:實例
[ root@CentOS ~]#awk  -F: '{print $1,$3}' score2.txt 
mage male
wang male
zhang female
li female
//跟FS效果一樣,只不過選項格式不一樣

OFS:輸出字段分隔符,默認(rèn)為空白字符

[ root@CentOS ~]#awk  -F: -v OFS='-' '{print $1,$3}'  score2.txt 
mage-male
wang-male
zhang-female
li-female
//先以 ":"分割,OFS='-',指定輸出的分隔符

RS:輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效

[ root@CentOS ~]#awk -v RS=':' '{print $0}' score2.txt 
mage
100
male
wang
90
male
zhang
80
female
li
100
female
//-v RS=':' :RS(行處理),在內(nèi)容中碰到':'就換行,輸入時的換行符

ORS:輸出時的換行符

[ root@CentOS ~]#awk -F: -v ORS='--' '{print $0}' score2.txt   
mage:100:male--wang:90:male--zhang:80:female--li:100:female--
//先以 ":"分割,輸出時以 '--'的分割符

NF:字段數(shù)量

[ root@CentOS ~]#awk  -F: '{print NF}' score2.txt 
3
3
3
3
1
//查看文件有幾個字段,如果寫成$NF意義就不一樣了。awk 中聲明的變量在print 里面無需寫'$'
[ root@CentOS ~]#awk  -F: '{print $NF}' score2.txt 
male
male
female
female
  100 female
 //打印出score2.txt文件的每行詞尾,因為NF是打印每行的字段數(shù)量,如果寫成$NF那就是NF的結(jié)果,如果NF是2,那么輸入$NF顯示的是2字段的字符串

NR:行號

[ root@CentOS ~]#awk  '{print NR}' score2.txt 
1
2
3
4
5
[ root@CentOS ~]#cat score2.txt 
mage:100:male
wang:90:male
zhang:80:female
li:100:female
li :  100 female
//顯示行號

FNR:各文件分別計數(shù),行號

[ root@CentOS ~]#awk  '{print $0,FNR}'  score.txt 
mage 100 male 1
wang 90 male 2
zhang 80 female 3
li 100 female 4
//后面的數(shù)字顯示的是行數(shù)編號

FILENAME:當(dāng)前文件名

[ root@CentOS ~]#awk  '{print FILENAME}' score.txt 
score.txt
score.txt
score.txt
score.txt
//因為score.txt里面有5行所有打印了5次,當(dāng)然我們也可以使用一種模式讓他只打印一次
[ root@CentOS ~]#awk  'END{print FILENAME}' score.txt      
score.txt
// END后面會講到

ARGC:命令行參數(shù)的個數(shù)

[ root@CentOS ~]#awk  '{print ARGC}' score2.txt   
2
2
2
2
2
//當(dāng)前有2個參數(shù),一個是awk,一個是score2.txt,打印5次是因為score2文件中有5行

ARGV:數(shù)組,保存的是命令行所給定的各參數(shù)

[ root@CentOS ~]#awk  '{print ARGV[0]}' score2.txt 
awk
awk
awk
awk
awk
[ root@CentOS ~]#awk  '{print ARGV[1]}' score2.txt  
score2.txt
score2.txt
score2.txt
score2.txt
score2.txt
//"ARGV[0]":表示數(shù)組中的第一個元素,"ARGV[1]":表示數(shù)組中的第二個元素

BEGIN/END模式

BEGIN{}: 僅在開始處理文件中的文本之前執(zhí)行一次

END{}:僅在文本處理完成之后執(zhí)行一次

AWK自定義變量:

變量(區(qū)分字符大小寫)
(1) -=value
(2) 在program中直接定義

[ root@CentOS ~]#awk -v test='hello word' 'BEGIN{print test}'
hello word
//定義test變量,并打印出來
[ root@CentOS ~]#awk  'BEGIN{test="hello word"; print test}'
hello word

printf命令:

格式化輸出:printf “FORMAT”, item1, item2, ...
(1) 必須指定FORMAT
(2) 不會自動換行,需要顯式給出換行控制符,\n
(3) FORMAT中需要分別為后面每個item指定格式符

格式符:需加"",與item一一對應(yīng)

                          %c:顯示字符的ASCII碼(專門顯示字符串)
                          %d,%i:顯示十進制整數(shù)
                          %e,%E 科學(xué)技術(shù)法數(shù)值顯示
                          %f:顯示為浮點數(shù)
                          %g,%G:以科學(xué)計數(shù)法或浮點型式顯示數(shù)值 
                          %s :顯示字符串
                          %u :無符號整數(shù)
                          %% :顯示%自身

修飾符

[.#]:第一個數(shù)字控制顯示的寬度;第二個#表示小數(shù)點后精度,%3.1f

-: 左對齊(默認(rèn)右對齊)%-15s
+:顯示數(shù)值的正負(fù)符號%+d

[ root@CentOS ~]#awk  -F: '{printf  "%-10s" "%10d\n",$1,$3}' /etc/passwd
root               0
bin                1
daemon             2
adm                3
lp                 4
sync               5
shutdown           6
halt               7
mail               8
uucp              10
operator          11
games             12
gopher            13
ftp               14
nobody            99
vcsa              69
saslauth         499
postfix           89
sshd              74
admin1           500
// "%-10s" :向左對齊,s是字符串(一定要跟文件中內(nèi)容一樣,/etc/passwd/中的$1是字符串,$3是數(shù)字所以寫的是 "%10d"),\n是換行
-----------------------------------------------------------------------------------------
[ root@CentOS ~]#awk  -F: '{printf  "NAME: %-10s  UID:%-10d\n",$1,$3}' /etc/passwd
NAME: root        UID:0         
NAME: bin         UID:1         
NAME: daemon      UID:2         
NAME: adm         UID:3         
NAME: lp          UID:4         
NAME: sync        UID:5         
NAME: shutdown    UID:6         
NAME: halt        UID:7         
NAME: mail        UID:8         
NAME: uucp        UID:10        
NAME: operator    UID:11        
NAME: games       UID:12        
NAME: gopher      UID:13        
NAME: ftp         UID:14        
NAME: nobody      UID:99        
NAME: vcsa        UID:69        
NAME: saslauth    UID:499       
NAME: postfix     UID:89        
NAME: sshd        UID:74        
NAME: admin1      UID:500 
//也可以添加一些字符串然看起來更美觀點

操作符

算數(shù)操作符:
    x+y , x-y, x*y , x/y , x^y , x%y
    -x:整數(shù)轉(zhuǎn)換成負(fù)數(shù)
    +:轉(zhuǎn)換為數(shù)值
    字符串操作符:沒有符號的操作符,字符串鏈接
    賦值操作符:
    =, +=, -= , *= , /= , %= ,^=
    比較操作符:
        >, >=, <, <=, !=, ==
    模式匹配符
        ~ :是否匹配
        !~:是否不匹配
    邏輯操作符:
        &&:并且
        ||:或者
        !:非
    條件表達(dá)式(三目表達(dá)式):
    selector?if-true-expression:if-false-expression 
//后面案例我們都會用到

awk PATTERN

(1)如果未指定:空模式,匹配每一行

(2) /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來

[ root@CentOS ~]#awk  '/^root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
//顯示以行首(^:行首的意思)為root的行

(3) relational expression:

關(guān)系表達(dá)式,結(jié)果為“真”才會被處理

真:結(jié)果為非0值,非空字符串

假:結(jié)果為空字符串或0值

[ root@CentOS ~]#awk  -F: '$3>200{print $1,$3}' /etc/passwd
saslauth 499
admin1 500
//匹配/etc/passwd中的$3,第三段是否大于200,如果大于就打印出來,否則不打印
[ root@CentOS ~]#awk  -F: '$NF=="/bin/bash"{print $NF}' /etc/passwd 
/bin/bash
/bin/bash
//$NF每行字段的最后一位字符串,如果匹配到的是 "/bin/bash"就打印出來

三目表達(dá)式:

[ root@CentOS ~]#awk -F: '{$3<500?user="is system":user="is common";{printf "%-10s %10s\n" ,$1,user}}' /etc/passwd
root        is system
bin         is system
daemon      is system
adm         is system
lp          is system
sync        is system
shutdown    is system
halt        is system
mail        is system
uucp        is system
operator    is system
games       is system
gopher      is system
ftp         is system
nobody      is system
vcsa        is system
saslauth    is system
postfix     is system
sshd        is system
admin1       is cmmon
//以":"分割,/etc/passwd中的第三行(uuid)小于500的就輸出"is system ",否則就輸入"is common",
//三目表達(dá)式格式:selector?if-true-expression:if-false-expression 

控制語句

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

if else 案例

[ root@CentOS ~]#awk  -F: '{if($3>=200) {printf "Common user: %-10s %8s\n",  $1,$3}else{printf "is system %-10s %10s\n",$1,$3}}' /etc/passwd
is system root                0
is system bin                 1
is system daemon              2
is system adm                 3
is system lp                  4
is system sync                5
is system shutdown            6
is system halt                7
is system mail                8
is system uucp               10
is system operator           11
is system games              12
is system gopher             13
is system ftp                14
is system nobody             99
is system vcsa               69
Common user: saslauth        499
is system postfix            89
is system sshd               74
Common user: admin1          500
// if判斷$3(/etc/passwd中的id)>=200就打印"Common user: $1,$3",否則就打印小于200(/etc/passwd中id)小于200的用戶和id("is system $1,$3")

while和for 循環(huán)

[ root@localhost ~]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) { if(length($i)>=3) {print $i,length($i)};i++}}' /etc/grub2.cfg 
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
crashkernel=auto 16
net.ifnames=0 13
linux16 7
/vmlinuz-0-rescue-e2b1c08415194abdb3672f06ea53672b 50
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
crashkernel=auto 16
net.ifnames=0 13

//對/etc/grub2.cfg進行操作,以行首為空白開頭最少一次或者多次并且后面跟linux16的行(^[[:space:]]*linux16),"i=1;while(i<=NF)",NF(統(tǒng)計每行的字段),i小于等于每行的字段總數(shù),
if(length($i)>=3:意思是每行的每段的字符串字?jǐn)?shù)大于等于3的打印出來,最后的{print $i,length($i)};i++}}
意思是:打印$i就是每行的段,length($i):將次匹配到的字符串放入這里面,最后的i++每次i的值都會+1,從1一直加到小于等于每行的字段數(shù)(只匹配設(shè)定前面設(shè)定條件的行)
//length 字符串長度
-----------------------------------------------------------------------------------------------
[ root@localhost ~]#awk  '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){ if(length($i)>=2) {print $i,length($i)}}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
ro 2
crashkernel=auto 16
net.ifnames=0 13
linux16 7
/vmlinuz-0-rescue-e2b1c08415194abdb3672f06ea53672b 50
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
ro 2
crashkernel=auto 16
net.ifnames=0 13

//跟上面效果一樣,只不過換成for循環(huán)

數(shù)組

[ root@CentOS ~]#awk 'BEGIN{user["w"]="wang";user["m"]="ma";print user["m"]}'   
ma
// 聲明一個數(shù)組,[]里面聲明了2個元素,元素和值必須加雙引號,打印時也許要輸入雙引號
//注意:var會遍歷array的每個索引
--------------------------------------------------------------------------------------------
[ root@CentOS ~]#awk  'BEGIN{user["w"]="wang";user["m"]="ma";for(i in user) {print user[i]}}'  
wang
ma
//通過for循環(huán)打印出數(shù)組中的元素
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • awk介紹awk變量printf命令:實現(xiàn)格式化輸出操作符awk patternawk actionawk數(shù)組aw...
    哈嘍別樣閱讀 1,744評論 0 4
  • 轉(zhuǎn)載 原文的排版和內(nèi)容都更加友好,并且詳細(xì),我只是在這里貼出了一部分留作自己以后參考和學(xué)習(xí),如希望更詳細(xì)了解AWK...
    XKirk閱讀 3,378評論 2 25
  • 本章主要學(xué)習(xí)內(nèi)容awk介紹 ?awk基本用法 ?awk變量 ?awk格式化 ?awk操作符 ?awk條件判斷 ?a...
    楠人幫閱讀 1,377評論 0 8
  • awk:報告生成器,格式化文本輸出 內(nèi)容: awk介紹 awk基本用法 awk變量 awk格式化 awk操作符 a...
    BossHuang閱讀 1,565評論 0 9
  • awk: grep,sed,awk grep:文本過濾 sed:文本編輯 awk:文本格式化工具; 1 什么是aw...
    木林森閱讀 1,919評論 0 16

友情鏈接更多精彩內(nèi)容