LINUX學習—AWK(LINUX三劍客)
awk是一個報告生成器,擁有強大的文字格式化能力;
也是一種文字處理工具,但其主要功能是從處理檔案中按照輸入的資訊格式後顯示的工具
awk是一種程式語言,支援條件判斷、陣列、迴圈等功能。用於在linux/unix下對文字和資料進行處理。資料可以來自標準輸入(stdin)、一個或多個檔案,或其它命令的輸出。它支援使用者自定義函式和動態正則表示式等先進功能,是linux/unix下的一個強大程式設計工具。它在命令列中使用,但更多是作為指令碼來使用。awk有很多內建的功能,比如陣列、函式等,這是它和C語言的相同之處,靈活性是awk最大的優勢。
LINUX三劍客特長
grep更適合單純的查詢或匹配文字 grep ‘pattern’ input-file…
sed更適合編輯匹配到的文字 sed [option] ‘AddressCommand’ file…
awk更適合格式化文字,對文字進行較複雜格式處理 awk [option] ‘pattern {action}’ file
awk基本語法
awk [options] ‘script’ file1 file2
awk [options] ‘pattern { action} pattern {action}…’ file
一、OPTION (常用選項)
-F:分隔符
-v var=value:賦值一個使用者自定義變數,將外部變數傳遞給awk
二、PATTERN(模式)
awk [option] ‘Pattern {Action}’ file1 file2
除了BEGIN 和END模式(不需要去讀取檔案的內容)外, awk中還有其他pattern,如:
1. 空模式,就是平時不新增任何模式引數的情況,即會匹配文字中的每一行,對於滿足條件的行執行相應的動作;如 awk '{print $0}' test
2. 關係運算模式; 如 awk 'NF==5 {print $0}' test
關係運算符有:
<:小於
<=:小於等於
==:等於
!=:不等於
>=:大於等於
>:大於
~:與對應的正則匹配則為真
!~: 與對應的正則不匹配則為真
3. 正則模式:
正則表示式通常被用來檢索、替換那些符合某個模式(規則)的文字
awk '/正則表示式/{print $0}' /etc/passwd
當正則表示式中已經存在/ 號時,需要使用轉義符對其進行轉義;
如awk'/\/bin\/bash$/{print $0}' /etc/passwd
除此之外,awk在使用正則模式時,使用到的正則用法屬於“擴充套件正則表示式”
當使用{x, y}這種次數匹配的正則表示式時,需要配合--posix或--re-interval選項,否則會報錯;
4. 行範圍模式:pat1,pat2
注意相鄰的正則表示式用逗號隔開,且都是以第一次匹配到的行為為準;
awk '/正則1/,/正則2/{動作}’ /some/file
這種方法還可以用多個關係表示式來達到效果:但相互之間用&&連線 如: awk 'NR>=3 && NR<=6 {print $0}' file
三、ACTION
1、print
print的使用格式:
print item1, item2,…
要點:
1、各專案之間使用逗號隔開,而輸出時則以空白字元分隔;
2、輸出的item可以為字串或數值、當前記錄的欄位(如
0,因此,如果想輸出空白行,則需使用print“”;
例:
#awk ‘BEGIN {print “line one\n line two\n line three”}’ (文字字串必須用雙引號,不能用單引號)
awk -F: ‘{print
2}’ /etc/passwd
awk變數
常用內建變數
-
0 這個變數包含執行過程中當前行的文字內容;
- FS 輸入欄位分隔符(預設是任何空格); FS=”:” ==-F:
- OFS 輸出欄位分隔符,(預設值是一個空格);
- RS 輸入記錄分隔符(輸入換行符),指定輸入時的換行符,預設換行;
- ORS 輸出記錄分隔符(輸出換行符),輸出時用指定符號代替換行符,預設換行;
- FS/OFS/RS/ORS使用時都要用-v選項
– 例:檢視當前系統所有使用者名稱:
– awk -F: ‘{print $1}’ /etc/passwd
- NF 表示欄位數,在執行過程中對應於當前的欄位數(即當前行被分割成了幾列),欄位數量;
- NR 表示記錄數,當前處理的文字行的行號;
- FNR 同NR,各檔案分別計數的行號;
- NF:一條記錄的欄位數; 是
- FILENAME 當前輸入檔案的名;
- ARGC 命令列引數的個數;
- ARGV 包含命令列引數的陣列,儲存的是命令列所給定的各引數;
這幾個內建變數和FS/OFS RS/ORS不同的是,它們是在大括號內使用,且可以直接使用,不需要用-v引數;
如果沒有以上內建變數,可以自己定義變數:
方法一: -v varname=value變數名區分字元大小寫; 如awk -v myVar=”testVar” ‘BEGIN{print myVar}’
方法二: 在action中直接定義。 awk ‘BEGIN{myvar=”ttt”;print myvar}’ 兩個獨立的語句,語句之間注意中間隔開需要使用分號,逗號會報錯。
這種同樣也可以一次性定義多個變數;
這四個內建變數在使用的時候需要使用-v引數(用於賦值於一個使用者定義的變數)
在action中的如果有多個語句,語句間用分號隔開;
2. printf
print只能實現簡單的文字輸出功能,並不能對文字格式進行改變,如果想要改變文字的格式,則需要awk中的另一個動作printf;
1) 在awk中使用printf時,指定的“格式”與列之間需要用逗號隔開,而使用printf命令時,指定的格式與傳入的文字不需要用逗號隔開
printf "%s \n" teststring
awk '{printf "%s\n", $1}' test
$0表示整行
2) 另外,在awk中,格式替換符的數量必須與傳入的引數的數量是相同的,即格式替換符必須與需要格式化的引數一一對應,但printf函式單獨使用時不需要,它可以逐個讀取並列印在終端
3)使用printf動作輸出的文字不會換行,如果需要換行,可以在對應的“格式替換符”後加入“\n”進行轉義;
printf命令詳解
\n : 轉義符;
printf命令語法:
printf format, item1, item2… (printf “指定的格式” “文字1”“文字2”“文字3”…)
printf “%s\n” abc def ghi jkl mno =echo/printf “abc \ndef \nghi \nmno” 這就是格式替換符引數的使用方法
要點:
1.同print最大的不同是需要指定format
2.format不會自動列印換行符 \n
3.format需要使用雙引號包括
4.format和C語言的格式化輸出很類似
3. 格式化替換符有(都是用百分號%表示):
%s 代替傳入的引數,並轉換為字串型別;(注意前面都是%)
%f 浮點格式;
%b 相對應的引數中包含轉義字元時,可以使用此替換符進行替換,對應的轉義字元會被轉義;
%c ASCII字元。顯示相對引數的第一個字元;
%d %i 十進位制整數;
%o 不帶正負號的八進位制值
%u 不帶正負號的十進位制值
%x 不帶正負號的十六進位制值,使用a至f表示10至15
%X 不帶正負號的十六進位制值,使用A至F表示10至15
%%表示“%”本身
4. 轉義字元(都是用\表示):
\a 警告字元,通常為ASCII的BEL字元
\b 後退
\c 抑制(不顯示)輸出結果中任何結尾的換行字元(只在%b格式指示符控制下的引數字串中有效),而且,任何留在引數裡的字元、任何接下來的引數以及任何留在格式字串中的字元,都被忽略;
\f 換頁(formfeed)
\n 換行
\r 回車
\t 水平製表符
\v 垂直製表符
\ 一個字面上的反斜槓字元,即“\”本身
\ddd表示1到3位數八進位制值的字元,僅在格式字串中有效
\0ddd表示1到3位的八進位制值字元
注意:當格式替換符有多個時,則引數依次傳遞到格式替換符中,即第一個引數對應第一個替換符,後一個引數對應第二個替換符,當本次格式化操作完成以後,則傳入下一步引數;
5. 修飾符
“數字”:如%7s 這裡的數字7對應的輸出寬度為7個字元寬,如果對應的輸出不足7個字元,則用空格補全,如果輸出長度超過7個字元,超出部分也會顯示;
此外數字修飾符還可以表示數字字元的寬度如 %s %12d \n,也可以表示數字小數點的格式 如%10s %-12.3f\n 這裡12.3表示替換符“%f”輸出寬度為12個字元,同時數字後面保留3位小數點;
“+” 表示如果數字為正,則顯示其前面的+號;
“-” 表示左對齊,不加這個符號表示右對齊;
- 輸出重定向
使用格式:
print items>outputfile
print items>>outfile
print items |command
注意:outputfile與command需要使用雙引號包括
例: awk -F: ‘{print 3|”sort -k1”}’ etc/passwd
awk [option] ‘pattern {action}’ file
{action} 可以分為{ }和action,前者相當於“組合語句”型別動作,後者為“輸出語句”型別動作
awk '{print $1} {print $2}' test ==awk '{print $1; print $2}' test
後者需要用分號分開
四、控制語句在awk中的應用
1:條件判斷語句
- if 條件判斷語句
語法:if (條件) {語句1;語句2;….}
例: awk ‘{if (NR==1) {print $0} }’ test5
需要注意的是,當print動作只有一個時,大括號可以省略,即可以寫成
awk '{ if "(NR==1) print $0}' test
但當print動作有多個時,大括號不能省略,否則會報錯,
awk '{if (NR==1) {print $1, $2}}' test
- “if…else”語句
“if…else”語法: if(條件) {語句1; 語句2;…} else {語句1; 語句2;…}
awk -F":" '{if ($3<500) {print $,"系統使用者"} else {print $1, "普通使用者"}}' /etc/passwd
- “if…else if …else”語句
“if…else if …else”語法: if(條件1) {語句1; 語句2;…} else if (條件2) {語句1; 語句2;…}
awk 'NR !=1' {if ($2<=30) {print $1, "年輕人"} else if ($2>=30 && $2<=50) {print $1, "中年人"} else {print $1, "老年人"}}' test7
* 2. for 迴圈語句 *
- for 迴圈語法格式1
for (初始化;布林表示式;更新){//程式碼語句}
例:awk ‘BEGIN {for ( i=1; i<=6; i++) {print i}}’
- for 迴圈語法格式2
for (變數in陣列){//程式碼語句}
3. while迴圈
- while 迴圈語法(當while對應的條件滿足時,則執行對應的語句,語句執行完成後,對條件進行修改。)
while (布林表示式){//程式碼語句}
例: awk ‘BEGIN {i=1; while (i<=5) {print i; i++}}’ 自定義變數的兩種表達方式
或 awk -v i=1 ‘BEGIN {while (i<=5) {print i; i++}}’
- do…while迴圈語法 (它與while迴圈的不同之處在於,while迴圈只有當滿足條件時才會執行對應的語句,而do…while則是無論是否滿足條件,都會先執行一遍do對應的程式碼,然後再判斷是否滿足while中對應的條件,滿足條件,則執行do對應的程式碼,如果不滿足條件,則不再執行do對應的程式碼。)
do {//程式碼語句} while (條件)
例:awk ‘BEGIN { i=1; do {print “test”; i++} while (i<1)}’列印一個test;
例2:awk ‘BEGIN {do {print “test”; i++} while (i<=5)}’ 列印6行test
4. continue 語句: 跳出”當前“迴圈
5. break語句:跳出“整個”迴圈
例:
awk 'BEGIN{for (i=0; i<=6; i++) {print i}}'
0
1
2
3
4
5
6
awk 'BEGIN{ for (i=0; i<=6; i++){if (i==3){continue}; print i}}'
0
1
2
4
5
6
awk 'BEGIN{for (i=0;i<=6;i++) {if (i==3){break}; print i}}'
0
1
2
6.exit語句:表示不再執行awk命令,相當於退出了當前的awk命令當時當exit和END模式同時使用時,表示exit語句之後的所有動作都不執行,END模式除外;
例: awk ‘BEGIN{print “start”; exit} {print $0} END{print “over”}’打印出來的結果是(start和over)
7.next語句:next 與continue有點類似,continue針對的是迴圈而已,它的作用主要是結束本次迴圈,而next 是針對逐行處理而言
值得注意的是,exit命令出現後會終止其後的所以語句,有點類似break awk ‘BEGIN{ for (i=0; i<=6; i++) { if (i==3) {break}; print i}}’
awk -F: ‘{if (NR%2==0} print NR; esle next}’ /etc/passwd #代表只顯示檔案/etc/passwd偶數行的使用者名稱;
五、內建函式
1:算數函式
1.1 rand函式、srand函式(初始化函式)、int函式。 (相當於awk語法中的action)
rand函式生成隨機數,一般使用時需要配合strand函式一起使用,否則rand函式返回的值將一直不變:
awak ‘BEGIN {print rand( )}’
awak ‘BEGIN{srand ( ); print rand ( )}’
這兩個直接生成的都是小數,要變成整數需要rand前100,然後在用int函式取整數,即:awk ‘BEGIN{srand ( ); print int (100 rand( ))}’
2:字串函式
- gsub函式: 替換指定範圍內的所有符合條件的字元,全域性替換;
cat test11
Allen Phillips (14)
Green Lee (9)
Willim Ken Allen (18)
awk '{gsub("l", "L", $1); print $0}' test11
返回: ALLen Phillips \n(表示換行) Green Lee \n WiLLim Ken Allen
awk '{sub("l", "L", $1); print $0}' test11
返回: ALlen Phillips \n Green Lee \n WiLlim Ken Allen.
- sub函式: 替換指定範圍內的單次替換,只替換第一次匹配到的字元;
length 函式:獲取指定字串的長度;
awk '{for (i=1; i<=NF;i++) {print $i, length($i)}}' test11 返回:14、9、18.
- index函式:獲取到指定字元位於整個字串中的位置;
awk ‘{print index ($0, “Lee”)}’ test11
返回0 7 0
使用index函式在整個檔案查詢Lee所在行,不存在,則返回值0,表示當前行不存在Lee,如找到,則返回Lee 所在行的字元位置; - split (string, array [, fieldseq [, seps]])
將string按照分隔符fieldseq進行分割,儲存在以array為名的陣列中,陣列下標從1開始計數。(將指定字串按照指定的分割符切割,將切割後的每一段賦值到陣列的元素中,從而動態建立陣列)
awk -F: ‘{if (NR>3) next; split ($NF, bash_dir,”/”); for (str in bash_dir) {print str, bash_dir[str]}’
if語句只處理前3行,split會將每一行最後的bash地址以斜槓分割並存儲於陣列bash_dir中,後面的for用於列印
awk -v ts=”大娃:二娃:三娃” ‘BEGIN{split (ts, huluwa, “:”); for (i in huluwa){print huluwa[i]}}’
返回 大娃 \n 二娃 \n 三\n2.6 - substr (string, start [, length]):擷取字串string的子串,從start開始,取length長度;若未指定長度,則返回從起始位置到字元末尾的子字串。
如:echo “123”|awk ‘{print substr ($0,1,1)}’ 返回1 - system(command)
執行系統命令,並將結果返回至awk命令
如:awk -F: ‘BEGIN{system (“date”)}’ 執行date命令,輸出到螢幕上 - systime ( )與 ( )
- systime ( )取得當前系統時間的時間戳
awk ‘BEGIN{now = systime ( ); print now }’ - strfime ( )將時間戳格式化為時間
awk ‘BEGIN{now=strftime (“%D”, systime( )); print now}’
- systime ( )取得當前系統時間的時間戳
- tolower (s)
將字串s所有字母轉為小寫 - toupper(s)
將字串s所有字母轉為大寫
**3. 使用者自定義函式 **
使用function關鍵字。格式如下:
function F_name([varible]) {statement} 可以使用return語句返回,格式為return valuw
將自定義函式儲存為awk指令碼,配合-f引數使用。
六、三元操作符
awk三元運算子 與列印奇偶行
1. 三元運算子
1. 第1種使用方式:條件?結果1:結果2 (表示如果條件成立,則返回結果1,反之則返回結果2)
可以用來替換if..else..語句
如:awk -F: ‘{if (
1,usertype}’ /etc/passwd
或:awk -F:’ {