敢用自己的名字做軟體名字的,都有非常強大的自信。比如,垠語言什麼的。
awk
的命名得自於它的三個創始人姓別的首字母,都是80來歲
的老爺爺了。當然也有四個人的組合:流行的GoF設計模式。但對於我這遊戲愛好者來說,想到的竟然是三位一體,果然是不爭氣啊。
它長的很像C,為什麼這麼有名,除了它強大的功能,我們姑且認為a
這個字母比較靠前吧。awk
比sed
簡單,它更像一門程式語言。
列印某一列
下面,這幾行程式碼的效果基本是相同的:列印檔案中的第一列。
#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,要簡單的滾瓜爛熟,複雜的耳熟能詳,畢竟有些大牛
,就喜歡寫這種指令碼呢。