AWK
AWK是一種用於處理文本的編程語言工具。它是 Linux中也是任何環境中現有的功能最強大的數據處理引擎之一。
基本語法
awk [options] 'program' file file ...
awk [options] 'PATTERN{action}' filefile ...
-FCHAR:定義輸入分隔符
1、awk的輸出
(1) 各項目之間使用逗號分隔,而輸出時則使用輸出分隔符分隔(輸出分隔符默認爲空白);
(2) 輸出的各item可以是字符串或數值、當前記錄的字段、變量或awk的表達式;如果是數值的話會被隱式轉換爲字符串後輸出;
(3) print後面item如果省略,相當於print$0;如果要輸出空白時,使用pirnt ""(在awk中,字串要使用雙引號“”);
使用示例:
A、顯示出系統中所有用戶的用戶名 [root@localhost ~]#awk -F: '{print $1}' /etc/passwd -F:表示指定輸入分隔符,'{print$1}'表示打印第一個字段,文件是/etc/passwd B、顯示系統中所有用戶名和用戶的shell信息,且顯示的時候兩字段不分隔 [root@localhost ~]#awk -F: '{print $1 $7}' /etc/passwd -F:表示指定輸入分隔符,'{print $1$7}'表示打印第一個字段和第七個字段當$1和$7之間爲空格時,所表示的是打印的結果是$1和$7是連在一起的,文件是/etc/passwd C、顯示系統中所有用戶名和用戶的shell信息,且顯示的時候兩字段分隔 [root@localhost ~]#awk -F: '{print $1,$7}' /etc/passwd -F:表示指定輸入分隔符,'{print $1$7}'表示打印第一個字段和第七個字段當$1和$7之間爲逗號時,所表示的是打印的結果是$1和$7是用空格分隔的,文件是/etc/passwd D、顯示出系統中所有用戶的用戶名,在用戶名前顯示hi字符並分隔顯示兩字段 [root@localhost ~]#awk -F: '{print "hi",$1}' /etc/passwd -F:表示指定輸入分隔符,'{print"hi",$1}'表示在$1前添加字符並打印出來,文件是/etc/passwd
2、awk的變量
內置變量,自定義變量
2.1、內置變量
FS:Field Seperator, 輸入時的字段分隔符
使用示例:
使用內置變量FS來顯示系統中用戶的用戶名和shell並分隔顯示 [root@localhost ~]#awk 'BEGIN{FS=":"}{print $1,$7}' /etc/passwd
RS:Record Seperator, 輸出行分隔符,也就是換行符
使用示例:
使用RS變量來換行顯示系統中所有用戶在passwd文件中的信息, [root@localhost ~]#awk 'BEGIN{RS=":"}{print }' /etc/passwd
OFS: Output Field Seperator, 輸出時的字段分隔符;
使用示例:
使用OFS變量顯示出使用:分隔系統中所用用戶和其對應的shell信息 [root@localhost ~]#awk 'BEGIN{FS=":";OFS=":"}{print $1,$7}' /etc/passwd
ORS: Outpput Row Seperator, 輸出時的行分隔符;
使用示例:
使用ORS變量顯示出使用以**爲行分隔符的所用用戶和其對應的shell信息 [root@localhost ~]#awk 'BEGIN{FS=":";ORS="**"}{print $1,$7}' /etc/passwd
內置變量很多,這裏列出常用的的變量:
NF:Numbers of Field,字段數
使用示例:
使用NF顯示列中的字段數 [root@localhost ~]#awk 'BEGIN{FS=":"}{print NF}' /etc/passwd
NR:Numbers of Record, 行數;當有多個文件時,所有文件的一併計數;
FNR:行數;各文件分別計數;
使用示例:
使用FNR顯示出文件的行數 [root@localhost ~]#awk 'BEGIN{FS=":"}{print NR $1,$7}' /etc/passwd;NR和FNR的使用格式相同,需要列出多個文件時只需在命令後再添加文件路徑即可
ARGV:數組,保存命令本身這個字符,awk'{print $0}' 1.txt 2.txt,意味着ARGV[0]保存awk,
ARGC: 保存awk命令中參數的個數;
FILENAME: awk正在處理的當前文件的名稱;
2.2 可自定義變量
-v var_name=VALUE
變量名區分字符大小寫;只能包含字母,下劃線且不能以數字開頭
自定義變量的兩種方式:
(1) 可以program中定義變量;
(2) 可以命令行中通過-v選項自定義變量;
自定義變量的使用
使用示例:
自定義變量配置兩種案例: [root@localhost ~]#awk 'BEGIN{a="hi awk";print a}' [root@localhost ~]#awk -v a="hi gawk" 'BEGIN{print a}'
3、awk的printf命令
命令的使用格式:printfformat, item1, item2,...
要點:
(1) 要指定format;
(2) 不會自動換行;如需換行則需要給出換行符\n
(3) format用於爲後面的每個item指定其輸出格式;
format格式的指示符都%開頭,後跟一個字符:
%c: 顯示字符的ASCII碼;
%d, %i: 十進制整數;
%e, %E: 科學計數法顯示數值;
%f: 顯示浮點數;
%g, %G: 以科學計數法格式或浮點數格式顯示數值;
%s: 顯示字符串;
%u: 顯示無符號整數;
%%: 轉義符,顯示%自身;
修飾符:
#:顯示寬度
-:左對齊
+:顯示數值的符號
.#: 取值精度
使用示例:
使用printf顯示用戶名和對應的shell,要求用戶名用20個字符的寬度,shell用30個字符的寬度 [root@localhost ~]#awk -F: '{printf "%20s,%30s\n",$1,$7}' /etc/passwd 示例中%20s表示20個字符寬,%30s\n表示30個字符寬並換行顯示,然後再將$1和$7套入%20s和%30s內,便可達到所要求的結果 浮點數使用案例:%f [root@localhost ~]#awk 'BEGIN{printf "%f\n",2.3659899}' 其他指示符跟浮點數的案例相同,這裏不再詳細給出案例
4、awk輸出重定向
print items > output-file
print items >> output-file
可以將print items得到的直接重定向到所指向的文件內
print items | command
也可以將結果直接使用管道符送給所需要的命令
在輸出重定向中也包含特殊文件描述符,分別有以下幾種
特殊文件描述符:
/dev/stdin: 標準輸入
/dev/stdout: 標準輸出
/dev/stderr: 錯誤輸出
5、awk的操作符
算術操作符:
x+y:x加y
x-y :x減y
x*y:x乘y
x/y:x除以y
x**y:x^y都表示x的y次方
x%y:取模運算
-x:負值
+x:轉換爲數值
字符串操作符:
只有一種符號叫做連接,這個操作沒有符號
賦值操作符:
=:等
+=:加等
-=:減等
*=:乘等
/=:除等
%=:取模
^=,**=:都表示次方
++:加加
--:減減
如果模式自身是=號,要寫爲/=/
比較操作符
<:
<=:
>:
>=:
==:
!=:不等於
~:模式匹配,左邊的字符串能夠被右邊的模式所匹配爲真,否則爲假;
!~:和~相反的匹配
邏輯操作符:
&&: 與
||:或
條件表達式:
selector?if-true-expression:if-false-expression
?表示如果爲真則執行if-true-expression,:表示否則則執行if-false-expression
使用示例:
判斷用戶的ID號: [root@localhost ~]#awk -F: '{$3>=500?utype="common user":utype="admin";print $1,"is",utype}'/etc/passwd $3表示用戶的ID號,用以比較是否大於等於500;?utype="commonuser"表示如果大於等於500就顯示爲common user,:utype="admin"表示否則就顯示爲admin;print$1,"is",utype表示打印用戶名後跟剛纔聲明的變量
函數調用:
function_name(argu1,argu2)
6、模式
1) Regexp:(正則表達式) 格式爲/PATTERN/
僅處理被/PATTERN/匹配到的行;
使用示例:
顯示/etc/passwd文件中包含root的行 [root@localhost ~]#awk -F: '/root/{print }' /etc/passwd
2)Expression:(表達式)比較表達式較多,其結果爲非0或非空字符串時滿足條件便會被處理;僅處理滿足條件的行;
使用示例:
顯示用戶的ID號大於等於500的用戶 [root@localhost ~]#awk -F: '$3>=500{print $1,$3}' /etc/passwd
3)Ranges:(範圍)行範圍,此前地址定界,startline, endline
僅處理範圍內的行
4) BEGIN/END: 特殊模式,僅在awk命令的program運行之前(BEGIN)或運行之後(END)執行一次;BEGIN通常用於首部,END通常用於尾部
5) Empty:空模式,匹配文件中的任意行;
7、常用的action
1)Expressions表達式
2)Control statements控制語句
3)Compound statements組合語句
4)inout statements輸入語句
5)output statements輸出語句
8、控制語句
1)if-else(條件判斷)
格式:if(condition條件) {then body語句,可有多個語句} else {else body}
使用示例:
A、判斷用戶的ID號: [root@localhost ~]#awk -F: '{if ($3>=500){print $1 "is a common user"}else{print $1"is an admin"}}' /etc/passwd B、判斷/etc/inittab文件中大於8個字段的行 [root@localhost ~]#awk '{if (NF>=8) {print}}' /etc/inittab 註釋:NF表示顯示字段數
2)while
格式:while(condition) {while body}(條件爲真時進行循環,爲假是退出循環)
使用示例:
A、顯示/etc/inittab文件中奇數的字段 [root@localhost ~]#awk '{i=1;while(i<=NF){printf "%s",$i;i+=2};print ""}'/etc/inittab 註釋:聲明i=1的變量,;號隔開表示一個語句; B、顯示/etc/inittab文件中字符個數大於等於6個 [root@localhost ~]#awk '{i=1;while (i<=NF){if (length($i)>=6) {print $i}; i++}}'/etc/inittab 註釋:length()內置函數:取字符串的長度
3) do-while循環
格式:do{do-while body} while (condition)(先進入循環執行一遍,再判斷爲真爲假,至少執行一次循環體)
4)for循環
格式:for(variable assignment變量賦值; condition條件; iteration process條件修正) {for body}
使用示例:
A、顯示/etc/inittab文件中奇數的字段 [root@localhost ~]#awk '{for(i=1;i<=NF;i+=2){printf "%s",$i};print " "}'/etc/inittab B、顯示/etc/inittab文件中字符個數大於等於6個 [root@localhost ~]#awk '{for (i=1;i<=NF;i++){if (length($i)>=6)print $i}}' /etc/inittab
for循環還可用來遍歷數組元素:
語法格式:for (iin array) {for body}
5)case語句
語法:switch (expression表達式) {caseVALUE or /RGEEXP/: statement1;... default: stementN}
6)循環控制
break(跳出循環)
continue(提前結束本輪循環,執行下一輪)
7)next
用於實現提前結束對本行的處理進而進入下一行的處理;
使用示例:
A、顯示/etc/passwd文件用戶的ID號爲奇數的 [root@localhost ~]#awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd 註釋:如果$3對2取模等於0,否則就顯示出來 B、顯示/etc/passwd文件中奇數行 [root@localhost ~]#awk -F: '{if(NR%2==0) next;print NR,$1}' /etc/passwd
9、數組
關聯數組:
array[index-expression]
其中index-expression: 可以使用任意字符串; 如果某數組元素事先不存在,那麼在引用時,awk會自動創建此元素並將其初始化爲空串;因此,要判斷某數組是否存在某元素,必須使用“index in array”這種格式;
如果要遍歷數組中的每一個元素,需要使用如下特殊結構:
for (var in array) {for body}
註釋:其中var會遍歷array的索引;而非元素值
state[LISTEN]++
state[ESTABLISHED]++
使用示例:
# netstat -tan | awk'/^tcp/{++state[$NF]}END{for (s in state) {print s,state[s]}}' # awk '{ip[$1]++}END{for (i inip) {print i,ip[i]}}' /var/log/httpd/access_log
刪除數組元素:
delete array[index]
10、awk的內置函數
split(string,array[,fieldsep[,seps]]):
功能:將string表示的字符串以fieldsep爲分隔符進行切片,並切片後的結果保存至array爲名的數組中;數組下標從1開始;
root:x:0:0::/root:/bin/bash
user[1]="root",user[2]
此函數有返回值,返回值爲切片後的元素的個數
使用示例:
# netstat -tn | awk'/^tcp/{lens=split($5,client,":");ip[client[lens-1]]++}END{for (i inip) print i,ip[i]}'
length(string)
功能:返回給定字串的長度
substr(string,start[,length])
功能:從string中取子串,從start爲起始位置爲取length長度的子串;