Linux文本處理之awk


    以前我介紹過sed,cut,tr,grep等等的命令來對文本進行處理,可是有時候發現這些命令並不能徹底的知足咱們的需求,直到我學習了awk,感受之前有些比較繁瑣的命令能夠根據awk輕易解決,這些命令的結合會給咱們處理文本帶來巨大的便利。shell


1、awk簡介express

    awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有本身的語言: AWK 程序設計語言 , 三位建立者已將它正式定義爲「樣式掃描和處理語言」。它容許您建立簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其餘的功能。vim

    awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤其強大。簡單來講awk就是把文件逐行的讀入,以分隔符將每行切片,切開的部分再進行各類分析處理。centos

    awk有3個不一樣版本: awk、nawk和gawk,未做特別說明,通常指gawk,gawk 是 AWK 的 GNU 版本。
數組

    awk程序的報告生成能力通常用來從大文本文件裏提取數據元素並將它們格式化成可讀的報告。最完美的樣例是格式化日誌文件  bash


 2、awk用法
app

    awk 'BEGIN{ commands } pattern{ commands } END{ commands }'tcp

    這條指令和之前的命令有些不一樣,他的命令有執行順序:
ide

        第一步:運行BEGIN{ commands }語句塊中的語句。函數

        第二步:從文件或標準輸入(stdin)讀取一行。而後運行pattern{ commands }語句塊,它逐行掃描文件,從第一行到最後一行反覆這個過程。直到文件全部被讀取完成。

        第三步:當讀至輸入流末尾時。運行END{ commands }語句塊。

        BEGIN語句塊在awk開始從輸入流中讀取行以前被運行,這是一個可選的語句塊,比方變量初始化、打印輸出表格的表頭等語句一般可以寫在BEGIN語句塊中。

        END語句塊在awk從輸入流中讀取全然部的行以後即被運行。比方打印所有行的分析結果這類信息彙總都是在END語句塊中完畢,它也是一個可選語句塊。

        pattern語句塊中的通用命令是最重要的部分,它也是可選的。假設沒有提供pattern語句塊,則默認運行{ print },即打印每一個讀取到的行。awk讀取的每一行都會運行該語句塊。

    這三個部分缺乏任何一部分均可以。

    選項:

        -F 指明輸入時用到的字段分隔符 

        -v var=value: 自定義變量

        -f scripfile 從腳本文件中讀取awk命令


 3、awk的變量

    變量分爲內置和自定義變量 

    內置變量:

     FS:輸入字段分隔符,默認爲空白字符 

[root@localhost(cyn) ~]$ awk -v FS=':' '{print $1,FS,$3}' /etc/passwd    #設置默認字符爲:
root : 0
bin : 1

    OFS:輸出字段分隔符,默認爲空白字符 

[root@localhost(cyn) ~]$ awk -v FS=':' -v OFS='!' '{print $1,$3}' /etc/passwd     #設置輸出爲!
root!0
bin!1

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

[root@localhost(cyn) ~]$ awk -v RS=' ' '{print }' /etc/passwd   #之前是按行進行操做,如今是按照RS定義的來,換行符依然是換行符
ftp:x:14:50:FTP
User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd
Network
Management:/:/sbin/nologin

    ORS:輸出記錄分隔符,輸出時用指定符號代替換行符     #制定輸出時的換行符

[root@localhost(cyn) ~]$ awk -v RS=' ' -v ORS='###' '{print }' /etc/passwd
ftp:x:14:50:FTP###User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd###Network###Management:/:/sbin/nologin
dbus:x:81:81:System###message###bus:/:/sbin/nologin
polkitd:x:999:998:User###for###polkitd:/:/sbin/nologin

    NF:字段數量 

###[root@localhost(cyn) ~]$ awk -F: '{print NF}' /etc/passwd       
7
7
7
7

    NR:行號 

[root@localhost(cyn) ~]$ awk '{print NR}' /etc/passwd
1
2
3
4
5
6

 FNR:各文件分別計數,行號 

[root@localhost(cyn) ~]$ awk '{print FNR}' /etc/fstab /etc/passwd   #統計兩個文件的行號
1
2
。。。
11
12
1
2

ARGC:命令行參數的個數 

[root@localhost(cyn) ~]$ awk '{print ARGC}' /etc/fstab /etc/passwd    #最前面的awk也算一個參數爲$0
3
3
3
3

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

[root@localhost(cyn) ~]$ awk '{print ARGV[1]}' /etc/fstab /etc/passwd 
/etc/fstab
/etc/fstab
[root@localhost(cyn) ~]$ awk '{print ARGV[0]}' /etc/fstab /etc/passwd 
awk
awk
[root@localhost(cyn) ~]$ awk '{print ARGV[2]}' /etc/fstab /etc/passwd 
/etc/passwd
/etc/passwd

    自定義變量

[root@localhost(cyn) ~]$ awk -v test='hello' '{print test}' /etc/passwd
hello 
hello


 4、格式化輸出

     格式化輸出:printf 「FORMAT」, item1, item2, ... 

    (1) 必須指定FORMAT 

    (2) 不會自動換行,須要顯式給出換行控制符,\n 

    (3) FORMAT中須要分別爲後面每一個item指定格式符 

    格式符:與item一一對應 

        %c: 顯示字符的ASCII碼 

        %d, %i: 顯示十進制整數 

        %e, %E:顯示科學計數法數值 

        %f:顯示爲浮點數 

        %g, %G:以科學計數法或浮點形式顯示數值 

        %s:顯示字符串

        %u:無符號整數 

        %%: 顯示

        %自身 

    修飾符:

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

        -: 左對齊(默認右對齊) 

        %-15s +:顯示數值的正負符號 %+d

[root@localhost(cyn) ~]$ awk -F: '{printf "%-15s%-5s\n",$1,$6}' /etc/passwd 
root           /root
bin            /bin 
daemon         /sbin


 5、awk操做符

    算術操做符: 

        x+y, x-y, x*y, x/y, x^y, x%y 

        -x: 轉換爲負數 

        +x: 轉換爲數值 

    字符串操做符:沒有符號的操做符,字符串鏈接

    賦值操做符: 

        =, +=, -=, *=, /=, %=, ^= 

        ++, -

    比較操做符: ==, !=, >, >=, <, <= 

    模式匹配符:

        ~:左邊是否和右邊匹配包含

        !~:是否不匹配  

[root@localhost(cyn) ~]$ awk -F: '($0 ~ /root/ ){print $1}' /etc/passwd    #支持正則
root
operator


 6、awk控制語句

    awk支持while,if  else,for循環,這部分

利用while計算100以內的和
[root@localhost(cyn) ~]$ awk BEGIN'{i=1;while(i<=100){sum+=i;i++};print sum}'
利用forjisuan 100以內的和
[root@localhost(cyn) ~]$ awk BEGIN'{for(i=1;i<=100;i++){sum+=i};print sum}'
利用for和if else計算奇數和
[root@localhost(cyn) ~]$ awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i};print sum}'


 7、awk數組

    關聯數組:array[index-expression] • index-expression: 

        (1) 可以使用任意字符串;字符串要使用雙引號括起來 

        (2) 若是某數組元素事先不存在,在引用時,awk會自動建立此元素,並將其值初始化爲「空串」 

    若要判斷數組中是否存在某元素,要使用「index in array」格式進行遍歷

    若要遍歷數組中的每一個元素,要使用for循環 

    for(var in array) {

        for-body

    } 

    注意:var會遍歷array的每一個索引 

[root@centos6(cyn) ~]$ awk -F: '{line[$7]++}END{for(i in line){print i,line[i]}}' /etc/passwd   #統計文件中某個單詞出現的次數
/sbin/shutdown 1
/bin/bash 1
/sbin/nologin 27
/sbin/halt 1
/bin/sync 1

[root@centos6(cyn) ~]$ netstat -tan|awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}' #統計監聽出現的次數
ESTABLISHED 1
LISTEN 10

 

 8、awk函數

    1.數值處理: 

        rand():返回0和1之間一個隨機數 

[root@centos6(cyn) ~]$ awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }' 
17
4
57
54
43
32
87
90

    2.字符串處理:

    length([s]):返回指定字符串的長度 

    sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並將第一個匹配的內容替換爲s 

[root@centos6(cyn) ~]$ echo "2018:08:29 10:08:30" |awk 'sub(/:/,"-",$1)'
2018-08:29 10:08:30

    gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並所有替換爲s所表示的內容 

[root@centos6(cyn) ~]$ echo "2018:08:29 10:08:30" |awk 'gsub(/:/,"-",$1)'
2018-08-29 10:08:30
[root@centos6(cyn) ~]$ echo "2018:08:29 10:08:30" |awk 'gsub(/:/,"-",$0)'
2018-08-29 10-08-30

    split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存至array所表示的數組 中,第一個索引值爲1,第二個索引值爲2,…

[root@centos6(cyn) ~]$ netstat -tan |awk '/^tcp\>/&& !($5 ~ "*") {split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
172.18.253.52 1
172.18.253.114 1
172.18.251.79 1
172.18.250.40 1
172.18.254.218 1
172.18.254.139 2

    3.自定義函數,awk的函數不須要加權限,直接運行

[root@centos6(cyn) ~]$ vim fun.awk
[root@centos6(cyn) ~]$ cat fun.awk 
function max(a,b){
	a>b?var=a:var=b
	return var
}
BEGIN{m=3;n=2;print max(m,n)}
[root@centos6(cyn) ~]$ awk -f fun.awk 
3


 9、awk中調用shell命令

    system命令 

    空格是awk中的字符串鏈接符,若是system中須要使用awk中的變量可使用空格分隔,或者說除了 awk的變量外其餘一概用""引用起來。 

[root@centos6(cyn) ~]$ awk 'BEGIN{score=100;system("name=zhangsan;echo $name score is "score )}'
zhangsan score is 100
[root@centos6(cyn) ~]$ awk BEGIN'{system("hostname")}'
centos6
相關文章
相關標籤/搜索