awk
awk是一種編程語言,對文本和數據進行處理
數據來自標準輸入、一個或多個文件、或其它命令的輸出、用戶自定義函數和動態正則表達式等
在命令行中或作爲腳本內建的功能,比如數組、函數等
語法形式
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)
常用命令選項
-F fs fs指定輸入分隔符,fs可以是字符串或正則表達式,如-F:
-v var=value 賦值一個用戶定義變量,將外部變量傳遞給awk
-f scripfile 從腳本文件中讀取awk命令
-m [fr] val 對val值設置內在限制
(-mf選項限制分配給val的最大塊數目;-mr選項限制記錄的最大數目)
模式:可以是以下任意一個
/正則表達式/:使用通配符的擴展集
關係表達式:使用運算符進行操作,可以是字符串或數字的比較測試
模式匹配表達式:用運算符~(匹配)和~!(不匹配)
BEGIN語句塊、pattern語句塊、END語句塊
操作:一個或多個命令、函數、表達式,換行符或分號隔開,位於大括號內
變量或數組賦值
輸出命令
內置函數
控制流語句
awk腳本基本結構
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
BEGIN語句塊、能夠使用模式匹配的通用語句塊、END語句塊
三個部分是可選的,腳本通常是被單引號或雙引號中
awk的工作原理
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
第一步:執行BEGIN{ commands }語句塊中的語句;
第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{ commands }語句塊,它逐行掃描文件,從第一行到最後一行重複這個過程,直到文件全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{ commands }語句塊。
BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中。
END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如打印所有行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊。
pattern語句塊中的通用命令是最重要的部分。如果沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。
awk內置變量(預定義變量)
awk運算與判斷
所有用作算術運算符進行操作,操作數自動轉爲數值,所有非數值都變爲0
> < 可以作爲字符串比較,也可以用作數值比較,關鍵看操作數如果是字符串就會轉換爲字符串比較。兩個都爲數字才轉爲數值比較
awk高級輸入輸出
讀取下一條記錄
awk中next語句使用:在循環逐行匹配,如果遇到next,就會跳過當前行,直接忽略下面語句。而進行下一行匹配。net語句一般用於多行合併:
cat 2.sh
a
b
c
d
e
awk 'NR%2==1{next}{print NR,$0;}' 2.sh
2 b
4 d
當記錄行號除以2餘1,就跳過當前行。下面的print NR,$0也不會執行。下一行開始,程序有開始判斷NR%2值。這個時候記錄行號是:2 ,就會執行下面語句塊:'print NR,$0'
分析發現需要將包含有“web”行進行跳過,然後需要將內容與下面行合併爲一行
cat 3.sh
web01[192.168.2.100]
httpd
tomcat
sendmail
web02[192.168.2.101]
httpd
postfix
web03[192.168.2.102]
mysqld
httpd
awk '/^web/{T=$0;next;}{print T":t"$0;}' 3.sh
web01[192.168.2.100]: httpd
web01[192.168.2.100]: tomcat
web01[192.168.2.100]: sendmail
web02[192.168.2.101]: httpd
web02[192.168.2.101]: postfix
web03[192.168.2.102]: mysqld
web03[192.168.2.102]: httpd
簡單地讀取一條記錄
awk getline用法:輸出重定向需用到getline函數。getline從標準輸入、管道或者當前正在處理的文件之外的其他輸入文件獲得輸入。它負責從輸入獲得下一行的內容,並給NF,NR和FNR等內建變量賦值。如果得到一條記錄,getline函數返回1,如果到達文件的末尾就返回0,如果出現錯誤,例如打開文件失敗,就返回-1。
getline語法:getline var,變量var包含了特定行的內容。
當其左右無重定向符|或<時:getline作用於當前文件,讀入當前文件的第一行給其後跟的變量var或$0(無變量),應該注意到,由於awk在處理getline之前已經讀入了一行,所以getline得到的返回結果是隔行的。
當其左右有重定向符|或<時:getline則作用於定向輸入文件,由於該文件是剛打開,並沒有被awk讀入一行,只是getline讀入,那麼getline返回的是該文件的第一行,而不是隔行。
執行linux的date命令,並通過管道輸出給getline,
然後再把輸出賦值給自定義變量out,並打印它:
awk 'BEGIN{ "date" | getline out; print out }' test
執行shell的date命令,並通過管道輸出給getline,然後getline從管道中讀取並將輸入賦值給out,
split函數把變量out轉化成數組mon,然後打印數組mon的第二個元素:
awk 'BEGIN{ "date" | getline out; split(out,mon); print mon[2] }' test
命令ls的輸出傳遞給geline作爲輸入,循環使getline從ls的輸出中讀取一行,並把它打印到屏幕。
這裏沒有輸入文件,因爲BEGIN塊在打開輸入文件前執行,所以可以忽略輸入文件。
awk 'BEGIN{ while( "ls" | getline) print }'
關閉文件
awk中允許在程序中關閉一個輸入或輸出文件,方法是使用awk的close語句。
close("filename")
filename可以是getline打開的文件,也可以是stdin,包含文件名的變量或者getline使用的確切命令。或一個輸出文件,可以是stdout,包含文件名的變量或使用管道的確切命令。
輸出到一個文件
awk中允許用如下方式將結果輸出到一個文件:
echo | awk '{printf("hello word!n") > "datafile"}'
或
echo | awk '{printf("hello word!n") >> "datafile"}'
設置字段定界符
默認的字段定界符是空格,可以使用-F "定界符" 明確指定一個定界符:
awk -F: '{ print $NF }' /etc/passwd
或
awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
在BEGIN語句塊中則可以用OFS=“定界符”設置輸出字段的定界符。