程序猿必知必會Linux命令之awk

前言

 

對於一名專業的程序員來講,Linux相關知識是必需要掌握的,其中對於文本的處理更是咱們常見的操做,好比格式化輸出咱們須要的數據,這些數據可能會來源於文本文件或管道符,或者統計文本里面咱們須要的數據出現的頻次以及總數等等。那麼這時候awk就很值得咱們去學習了。html

 

正文

 

在Linux中,awk、sed、grep被稱爲「三劍客」,都跟文本操做有關,那他們各自有什麼特色呢?git

 

grep:適合用於單純的查找與匹配。
sed:適合修改匹配到的文本。
awk:適合對文本進行復雜的格式化處理。程序員

 

因此awk是一種文本處理的編程工具語言,它會掃描輸入數據的每一行,若與當前的pattern匹配,則執行對應的動做,若不匹配或者當前行的動做已執行完成的話則會繼續下一行的處理,直到數據讀取完成。github

 

基本用法

 

awk基本語法

 

awk [option] 'pattern{action}' files

//awk 關鍵字
//[option] 能夠省略的一些參數
//'pattern{action}' pattern 是匹配的條件,可省略。action是具體執行的動做。
//files 是咱們操做的文件,可多文件操做。

  

awk典型用法

 

 

awk '{
    BEGIN{action ...} //執行前語句
    {action...} //匹配處理每行數據
    END{action...} //執行後語句
}'

  

 
awk內置變量

 

變量 做用
FS 輸入字段分割符,默認空白字符
OFS 輸出字段分割符,默認空白字符
RS 輸入記錄也就是行數據分隔符,默認換行符
ORS 輸出記錄也就是行數據分隔符,默認換行符
NF 當前行被分割成多少個字段的數量
NR 當前的行號,從1開始,在多文件中該值也會累加
FNR 當前的行號,從1開始,與NR不一樣,它是對應各自的文件累加
FILENAME 當前的文件名
$0 當前行數據
$1 ~ $n 獲取該行記錄的第N個字段

 

示例:docker

 

[root@wangzh awkdemo]# cat /etc/passwd

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
...

  

//利用FS修改輸入字段分割符,而後輸出行號以及第1第7個字段的值
[root@wangzh awkdemo]# awk 'BEGIN{FS=":"} {print NR,$1,$7}'  /etc/passwd
1 root /bin/bash
2 bin /sbin/nologin
3 daemon /sbin/nologin
4 adm /sbin/nologin
...

  

//跟上一個例子的區別,添加了標題的輸出,修改了輸出字段的分隔符爲"-"
[root@wangzh awkdemo]#awk 'BEGIN{FS=":";print "Result Title"} {print NR,$1}' OFS="-"  /etc/passwd
Result Title
1-root
2-bin
3-daemon
4-adm
...

  

 
運算符與正則

 

這塊內容的話,跟咱們大多數編程語言都比較類似,大夥能夠橫向對比一下,對於剛接觸的同窗能夠會理解一點。編程

算術運算符:==,>,<,!=,>=,<=,+,-bash

邏輯運算符:&&,||編程語言

正則:函數

  • /regex/ 該行內容匹配上正則就執行動做工具

  • ! /regex/ 該行內容未匹配上正則就執行動做

  • $1 ~ /regex/ 只在第一個字段匹配正則

  • $1 !~ /regex/ 第一個字段不匹配該正則

 

案例:

 

//'-F:' 是定義輸入字段分割字符的另外一種方法,這個匹配第一個字段包含'root'的信息
[root@wangzh awkdemo]# awk -F: '$1 ~ /root/ {print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
dockerroot:x:994:991:Docker User:/var/lib/docker:/sbin/nologin

  

//輸出第一行到第三行的數據
[root@wangzh awkdemo]# ip addr | awk 'NR>=1 && NR<=3 {print}'
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo

  

if/for/while

 

if(condi1){action1} else if(condi2){action2} else{action3}

---

for(i=1;i<=NR;i++){
    action1;
    action2;
    ...
}

---

while(condi){
    action1;
    ...
}
 

能夠看到,用法幾乎跟不少編程語言是一致的,下面給出一個簡單的示例。

 

[root@wangzh awkdemo]# cat t1.log
1 aa
3 bb
10 cc
9 dd
5 ee

---

//判斷每行第一個字段是不是3-9之間的數字,而後輸出對應的結果
[root@wangzh awkdemo]# awk '{if($1 ~ /[3-9]/){print "yes"} else {print "no"}}' t1.log
no
yes
no
yes
yes

  

內置函數

 

在awk中,內置函數也很多,幫助咱們封裝了一些字符操做、數學操做等,具體的用法還需各位查閱幫助手冊,下面就先介紹一下比較經常使用的 sub() 函數的用法。

 

參考:http://www.cnblogs.com/chengmo/archive/2010/10/08/1845913.html

 

sub( Ere, Repl, [ string ] )

string參數是須要處理的字符串,默認是$0也就是當前行
Ere正則匹配的字符串用Repl的字符串來替換

 

[root@wangzh awkdemo]# awk 'BEGIN{info="this is a test2019test!";sub(/[0-9]+/,"!",info);print info}'
this is a test!test!

  

實戰案例

 

統計文本中關鍵字出現的次數

 

[root@wangzh awkdemo]# cat data.txt
ID NAME
1 xiaom
2 zsan
3 lisi
4 lisi
5 lisi
6 xiaom
7 lisi
8 xiaom
9 xiaoh
10 zsan


[root@wangzh awkdemo]# awk 'BEGIN{print "Statistics Result >>>>>"} {if(FNR>1){result[$2]+=1}} END{for(i in result){print i,"count:"result[i]} {print "over >>>>"}}' data.txt
Statistics Result >>>>>
xiaoh count:1
xiaom count:3
zsan count:2
lisi count:4
over >>>>

  

結語

 

本篇文章的目的是讓沒接觸這塊內容的同窗對文本處理有一個感性的認識,對於掌握awk絕對不是隻看就能夠學會的,必需要本身動手實踐起來,遇到問題多查手冊,相信很快你也是一個文本處理高手。

 

---------------------------------------------------------

 

公衆號博文同步Github倉庫,有興趣的朋友能夠幫忙給個Star哦,碼字不易,感謝支持。

https://github.com/PeppaLittlePig/blog-wechat

 

推薦閱讀

 

Java日誌正確使用姿式

Java異常處理最佳實踐及陷阱防範

論JVM爆炸的幾種姿式及自救方法

 

看完本文有收穫?請轉發分享給朋友吧

關注「深夜裏的程序猿」,分享最乾的乾貨

 

相關文章
相關標籤/搜索