Linux中最常用的一套“AWK“

JAVA一方發表於2020-02-14

敢用自己的名字做軟體名字的,都有非常強大的自信。比如,垠語言什麼的。

awk的命名得自於它的三個創始人姓別的首字母,都是80來歲的老爺爺了。當然也有四個人的組合:流行的GoF設計模式。但對於我這遊戲愛好者來說,想到的竟然是三位一體,果然是不爭氣啊。

它長的很像C,為什麼這麼有名,除了它強大的功能,我們姑且認為a這個字母比較靠前吧。awksed簡單,它更像一門程式語言。

列印某一列

下面,這幾行程式碼的效果基本是相同的:列印檔案中的第一列。

#Java
System.out.println(aStr.split(" ")[0]);

#Python
print(aString.split(" ")[0])

#cut 命令
cut -d " " -f1   file

#awk命令
awk '{print $1}' file複製程式碼

這可能是awk最常用的功能了:列印檔案中的某一列。它智慧的去切分你的資料,不管是空格,還是TAB,大概率是你想要的。

對於csv這種檔案來說,分隔的字元是,。AWK使用-F引數去指定。以下程式碼列印csv檔案中的第1和第2列。

awk -F "," '{print $1,$2}' file複製程式碼

由此,我們可以看出一個基本的awk命令的組成部分。

一般的開發語言,陣列下標是以0開始的,但awk的列$是以1開始的,而0指的是原始字串。

網路狀態統計

本小節,採用awk統計netstat命令的一些網路狀態,來看一下awk語言的基本要素。netstat的輸出類似於:

其中,第6列,標明瞭網路連線所處於的網路狀態。我們先給出awk命令,看一下統計結果。

netstat  -ant | 
awk ' \
    BEGIN{print  "State","Count" }  \
    /^tcp/ \
    { rt[$6]++ } \
    END{  for(i in rt){print i,rt[i]}  }'複製程式碼

輸出結果為:

State Count
LAST_ACK 1
LISTEN 64
CLOSE_WAIT 43
ESTABLISHED 719
SYN_SENT 5
TIME_WAIT 146複製程式碼

下面這張圖會配合以上命令詳細說明,希望你能瞭解awk的精髓。

乍一看,好嚇人的命令,但是很簡單。awk和我們通常的程式不太一樣,它分為四個部分。

1、BEGIN 開頭部分,可選的。用來設定一些引數,輸出一些表頭,定義一些變數等。上面的命令僅列印了一行資訊而已。

2、END 結尾部分,可選的。用來計算一些彙總邏輯,或者輸出這些內容。上面的命令,使用簡單的for迴圈,輸出了陣列rt中的內容。

3、Pattern 匹配部分,依然可選。用來匹配一些需要處理的行。上面的命令,只匹配tcp開頭的行,其他的不進入處理。

4、Action 模組。主要邏輯體,按行處理,統計列印,都可以。

注意點

1、awk的主程式部分使用單引號‘包圍,而不能是雙引號
2、awk的列開始的index是0,而不是1

例子

我們從幾個簡單的例子,來看下awk的作用。

1、輸出Recv-Q不為0的記錄

netstat -ant | awk '$2 > 0 {print}'複製程式碼

2、外網連線數,根據ip分組

netstat -ant | awk '/^tcp/{print $4}' | awk -F: '!/^:/{print $1}' | sort | uniq -c複製程式碼

3、列印RSS實體記憶體佔用

top -b -n 1 | awk 'NR>7{rss+=$6}END{print rss}複製程式碼

4、過濾(去掉)空白行

awk 'NF' file複製程式碼

5、列印奇數行

awk 'a=!a' file複製程式碼

6、輸出行數

awk 'END{print NR}' file複製程式碼

這些命令,是需要了解awk的一些內部變數的,接下來我們來介紹。

內建變數

FS

下面的兩個命令是等價的 。

awk -F ':'  '{print $3}' file
awk 'BEGIN{FS=":"}{print $3}' file複製程式碼

BEGIN塊中的FS ,就是內部變數,可以直接指定或者輸出。如果你的檔案既有用,分隔的,也有用:分割的,FS甚至可以指定多個分隔符同時起作用。

FS="[,:|]"複製程式碼

其他

OFS 指定輸出內容的分割符,列數非常多的時候,簡化操作。相似命令:

awk -F ':' '{print $1,"-",$2,"-",$4}' file
awk 'BEGIN{FS=":";OFS="-"}{print $1,$2,$4}' file 複製程式碼

NF 列數。非常有用,比如,過濾一些列數不滿足條件的內容。

awk -F, '{if(NF==3){print}}' file複製程式碼

NR 行號,例如,下面兩個命令是等價的。

cat -n file
awk '{print NR,$0}' file複製程式碼

RS 記錄分隔標誌
ORS 指定記錄輸出的分隔標誌

FILENAME 當前處理的檔名稱,在一次性處理多個檔案時非常有用

程式語言特性

數學運算

從上面的程式碼可以看出,awk可以做一些簡單的運算。它的語言簡潔,不需要顯示的定義變數的型別。

比如上面的 rt[$6]++,就已經預設定義了一個叫做rt的hash(array?),裡面的key是網路狀態,而value是可以進行運算的(+-*/%)。

包含一些內建的數學運算(有限)

int
log
sqrt
exp
sin
cos
atan2
rand
srand複製程式碼

字串操作

類似其他語言,awk也內建了很多字串操作函式。它本來就是處理字串的,所以必須強大。

length(str) #獲取字串長度
split(input-string,output-array,separator)
substr(input-string, location, length)複製程式碼

語言特性

awk是個小型的程式語言,看它的基本語法,如果你需要複雜一點的邏輯,請自行深入瞭解,包括一些時間處理函式:

# logic
if(x=a){}
if(x=a){}else{}
while(x=a){break;continue;}
do{}while(x=a)
for(;;){}

# array
arr[key] = value
for(key in arr){arr[key]}
delete arr[key]

asort(arr) #簡單排序複製程式碼

據說,awk可以勝任所有的文字操作。因為它本身就是一門語言啊。

End

曾經使用awk編寫過複雜的日誌處理和統計程式。雖然比寫sed舒暢了很多,但還是備受煎熬。更加上現在有各種nawk,gawk版本之間的區別,所以業務複雜度一增長,就習慣性的轉向更加簡潔、工具更全的python。

awk處理一些簡單的文字還是極其方便的,最常用的還是列印某一列之類的,包括一些格式化輸出。對於awk,要簡單的滾瓜爛熟,複雜的耳熟能詳,畢竟有些大牛,就喜歡寫這種指令碼呢。


相關文章