01. 簡介
AWK是一個文本(面向行和列)處理工具,同時它也是一門腳本語言。
AWK其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。后來AWK加入GUN后,更名為GAWK。
在Linux系統中,已經自動集成了GAWK,並兼容AWK。
02. 語法、選項
語法
gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
gawk [ POSIX or GNU style options ] [ -- ] program-text file ...
選項
POSIX options: GNU long options: (standard)
-f progfile --file=progfile 從程序文件中讀取AWK程序,可以使用多個"-f"選項。
-F fs --field-separator=fs 設置輸入字段的分隔符(預定義變量FS的值)。
-v var=val --assign=var=val 在程序開始執行前,聲明變量。這些變量=值可用於AWK
程序的BEGIN規則。
Short options: GNU long options: (extensions)
-b --characters-as-bytes 將字符串視為單字節字符輸入。
-c --traditional 在兼容模式下運行。在兼容模式下,沒有一個特定的GUN
的擴展被識別。
-C --copyright 在標准輸出上打印簡短的GUN版權信息后並退出。
-d[file] --dump-variables[=file] 打印全局變量、其類型和最終值的排序列表並轉儲到指
定文件。如果沒有指定任何文件,則默認使用名為
awkvars的文件。
-D[file] --debug[=file] 啟用對AWK程序的調試功能。默認情況下,調試器以交互
式從鍵盤讀取命令(標准輸入)。可選的"file"參數允
許指定一個帶有命令列表的文件,調試器可以以非交互
式地執行這些命令。
-e 'program-text' --source='program-text' 允許在命令行直接輸入'AWK指令'作為AWK程序的源代
碼。此選項允許與"-f"選項混合使用,它主要用於在
Shell腳本中使用中大型AWK程序。
-E file --exec=file 與"-f"選項相似,這應該與#!腳本一起使用,特別是對
於CGI應用程序,避免從命令行的URL上傳入選項或源代
碼(!)。這個選項將禁用命令行變量的指定。
-g --gen-pot 掃描並解析AWK程序,並在標准輸出上生成GUN.pot格式
的文件,其中包含程序中所有可本地化字符串的條目。
-h --help 在標准輸出上打印可用選項的簡短幫助信息。
-i includefile --include=includefile 加載AWK源庫。這將使用AWKPATH環境變量來搜索庫。
-l library --load=library 載入共享lib庫。
-L[fatal|invalid] --lint[=fatal|invalid] 提供有關可疑或不可移植到其他AWK實現構造的警告。
-M --bignum 強制對數字進行任意精度的運算。如果GAWK為編譯
GNU MPFR和MP庫,則此選項無效。
-N --use-lc-numeric 識別輸入數據中的八進制和十六進制值,請謹慎使用此
項!
-n --non-decimal-data 開啟GAWK在解析輸入數據時使用語言環境的小數點字
符。
-o[file] --pretty-print[=file] 格式化輸入的AWK程序,將漂亮格式版本的AWK程序輸出
到指定文件。如果未指定文件則將輸出到名
為"awkprof.out"的文件中在當前目錄。
-O --optimize 啟用程序優化功能。對於常量的折疊和遞歸函數的尾部
調用消除。
-p[file] --profile[=file] 啟用會話分析功能。並將分析數據寫入到指定文件。
-P --posix 打開兼容模式。但有以下限制:
- \x 無法識別轉義序列;
- 當FS設置為單個空格時,只有空格和制表符Tab作為字
段分隔符,忽略換行符;
- 不允許在行的后面輸入?和:;
- 無法識別關鍵字函數func;
- 運算符**和**=不能代替^和^=。
-r --re-interval 使用正則表達式支持間隔表達式(比如{n,m}),默認情
況下它們是啟用的。
-S --sandbox 在沙盒中運行GAK,禁用system()函數,使用getline重
定向輸入,使用print和printf重定向輸出,並動態加載
擴展。
-t --lint-old 提供有關不可移植到UNIX的AWK初始構造版本的警告。
-V --version 在標准輸出上打印GAWK的版本信息。
03. 執行AWK程序
AWK程序由一系列模式操作語句和可選函數定義組成。
AWK處理順序:BEGIN{}-->{}-->END{}
BEGIN{} BEGIN規則塊中的語句在開始處理文件中的文本之前執行一次。
END{} END規則塊中的語句在文本處理完成之后執行一次
---
@include "filename"
@load "filename"
pattern { action statements }
function name(parameter list) { statements }
---
GAWK首先從指定的程序文件中讀取程序源,從--source選項讀取,或者從命令行上的第一個非選項參數讀取。-f和--source選項在命令行可以多次使用。
另外,可以使用以@include開頭的行將其他源文件包含到程序中,從而使庫的使用更容易。這相當於使用-i選項。
可以使用@load開頭的行將共享庫加載到程序中,這相當於使用-l選項。
當設置了AWKPATH環境變量時,使用-f和-i選項的時候只需要指定文件名稱,則GAWK會自動從AWKPATH變量設置的目錄下搜素到該文件。如果沒有設置AWKPATH環境變量,則默認從"/usr/local/share/awk"目錄下搜索。如果-f選項中包含"/"字符則執行路徑搜索。
當設置了AWKLIBPATH環境變量時,這相當於使用-l選項。如果這個環境變量不存在,則使用默認路徑"/usr/lib/lib/gawk"
GAWK執行AWK程序會按照以下順序執行。首先,執行通過-v選項指定的所有變量賦值。接下來,GAWK會將程序編譯成內部格式。然后,GAWK會執行BEGIN規則(如果有)中的代碼,然后繼續讀取ARGV數組中命名的每個文件(直到ARGV[ARGC])。如果命令行上沒有指定文件,則GAWK會從標准輸入中讀取。
如果命令行上文件名中具有"var=val"形式,則會將其視為變量賦值。變量var將被賦值為val,但是這將發生在任何BEGIN規則之后執行。
如果ARGV中的某個特定元素的值是空("")的,則GAWK會跳過它。
對於每個輸入文件,如果存在一個BEGINFILE規則,在處理文件內容之前,GAWK會執行相關代碼。在處理完文件后,GAWK會執行與ENDFILE關聯的代碼。
對於輸入的每條記錄,GAWK都會測試它是否匹配AWK程序中的任何模式。對於記錄匹配的每個模式,GAWK執行相關的動作。
最后,在所有的輸入都用完之后,GAWK將執行END規則(如果有)中的代碼。
04. 變量、記錄和字段
記錄(Records)
一行表示一個記錄。默認情況下記錄由換行符分隔。
我們可以通過給RS內置變量重新賦值來修改分隔符,從而修改記錄的分隔方式。分隔符允許是任意字符。另外RS允許是一個正則表達式,這將以能夠被正則表達式匹配到的字符作為分隔符。然后,當在兼容模式下的時候,只使用字符串中的第一個字符來分隔記錄。
字段(Fields)
一段字符串表示一個字段。默認情況下字段由空格分隔。
讀取每個輸入記錄時,GAWK會使用FS內置變量作為字段的分隔符,將記錄分割成多個字段。FS允許是任意字符或正則表達式。
變量和常量(Variables and Constant)
用特殊的非數字的字符來承載可變化的值,將其稱之為變量。
量,測量東西的容器。用量來承載可變的值,在編程語言中將這個容器通常稱之為變量,即可變化的量。不可變化的量稱之為常量。
foo = 5 # 聲明變量,創建變量並賦值
print foo # 調用變量,打印變量的值
內置變量(Built-in Variables)
$n 可以使用$1~n來獲取記錄中分隔好的對應每個數值位置的字段。
$0 獲取記錄。
ARGC 命令行參數的數量(不包括選項和程序源)。
ARGIND 判斷正在處理腳本文件的序號,如果只有一個腳本文件,則序號等於1。
ARGV 命令行參數組成的數組。可以使用數字索引取數組里面的值,比如ARGV[0]。
BINMODE 在非POSIX系統上,指定對文件的I/0使用"二進制"模式。
有以下幾個固定值:
1 輸入文件
2 輸出文件
3 所有文件
r 輸入文件
w 輸出文件
rw 所有文件
CONVFMT 將數字轉換成字符類型時的格式,默認格式是"%.6g"。%表示格式化字符的意思,.
.6表示小數點后面保留6位,g是格式化字符的標識,決定將浮點轉換成科學計數法
或者浮點型。例如:1.131425678,則當設置了CONVFMT="%.3f"后則輸出的字符串
為1.13。一般用"%f",這表示格式化字符串是一個浮點數。
ENVIRON 當前系統環境變量組成的數組。這是一個關聯數組,可使用關聯的鍵的名稱獲取對
應鍵的值。例如:ENVIRON["HOME"]
ERRNO 當系統錯誤發生在獲取行(getline)期間,當設置了ERRNO的值(這是一串關於錯錯
誤的描述信息),則會將該值打印出來。該值受非英語地區翻譯的限制。
FIELDWIDTHS 使用指定寬度大小將一個字段(以空格分隔的)分隔成多個字段。例如:
FIELDWIDTHS="1 2 1"則可以將abcd分割成a bc d。
FILENAME 當前輸入文件的名稱。如果命令行上沒有指定任何文件,則該變量的值等於"-"。
FNR 當前輸入文件的記錄的編號,即行號。當存在多個文件時,每個文件的記錄號都是
從1開始的。
FPAT 記錄中字段內容的正則表達式。當設置此變量時,字段與正則表達式匹配,而不是
使用FS的值作為字段分隔符。
FS 輸入字段分隔符,默認為空格。
FUNCTAB 一個數組,其索引和對應值是程序中所有用戶定義的函數或擴展函數的名稱。
IGNORECASE 控制對所有正則表達式操作字符串時是否區分大小寫。如果IGNORECASE是一個非零
值時,當執行正則表達式時,在規則中比較字符串和模式匹配時,使用FS和FPAT拆
分字段時,使用RS分隔字段時,使用~和!~模糊匹配時,以及使用gensub()、
gsub()、index()、match()、patsplit()、split()和sub()內置函數時都忽略大小
寫。但是,數組下標"索引或鍵"不受影響。但是asort()和asorti()函數會收到影
響。
默認情況下,IGNORECASE的初始值等於0,即區分大小寫。
LINT 在AWK程序中提供對--lint選項的動態控制。如果為true,則GAWK打印警告。如果
為false,則不會。當值等於"fatal"時,警告將變成致命錯誤。
NF 當前輸入記錄中的字段數量。
NR 當前輸入文件記錄的總數。
OFMT 數字的輸出格式,默認是"%.6g"。
OFS 輸出字段分隔符,默認是空格。
ORS 輸出記錄分隔符,默認是換行符。
PREC 任何精度浮點數的工作精度,默認為53。
PROCINFO 這是一個數組,該數組中的元素提供有關於正在運行的AWK程序的相關信息。
PROCINFO["egid"] 當前進程的EGID。
PROCINFO["strftime"] AWK程序中使用的時間格式。
PROCINFO["euid"] 當前進程的EUID。
PROCINFO["FS"] 運行AWK程序所使用的字段分隔符對應的
內置變量"FS\FPAT\FIELDWIDTHS"。
PROCINFO["identifiers"] 一個子數組,以AWK程序中使用的所有標
識符的名稱為索引。元素的值是以下其
中一個:
"array" 標識符是數組。
"builtin" 標識符是內置函數。
"extension" 標識符是通過@load或-l
加載的擴展功能。
"scalar" 標識符是標量。
"untyped" 標識符是無類型的。
"user" 標識符是用戶自定義函
數。
PROCINFO["gid"] 當前進程的GID。
PROCINFO["pgrpid"] 當前進程的進程組ID。
PROCINFO["pid"] 當前進程的ID。
PROCINFO["ppid"] 當前進程的父進程PID。
PROCINFO["uid"] 當前進程的UID。
PROCINFO["sorted_in"] 如果此元素存在於PROCINFO中,則其值
控制在FOR循環中遍歷數組元素的順序。
PROCINFO["input", "READ_TIMEOUT"] 從輸入中讀取數據的超時時間(毫秒)。
其中輸入是重定向字符串或文件名,值
為0或小於0表示沒有超時。
PROCINFO["mpfr_version"] MPFR庫的版本。
PROCINFO["gmp_version"] MP庫的版本。
PROCINFO["prec_max"] MPFR庫支持浮點數的最大精度。
PROCINFO["prec_min"] MPFR庫支持浮點數的最小精度。
PROCINFO["api_major"] 擴展API的主要版本。
PROCINFO["api_minor"] 擴展API的次要版本。
PROCINFO["version"] GAWK的版本。
ROUNDMODE 舍入模式,用於數字的任意精度運算,默認為"N"(IEEE-754 roundTiesToEven
mode)。"N"或者"n"表示舍入為偶數,"U"或者"u"表示舍入為正數,"Z"或者"z"表
示舍入為零。類似於四舍五入的一種模式。
RS 輸入記錄分隔符,默認是換行符。
RT 記錄終止符,GAWK將RT設置為與RS指定的字符或正則表達式匹配的輸入文本。
RSTART match()匹配的第一個字符的索引。如果沒有匹配則為0,這意味着字符索引是從1
開始。
RLENGTH match()匹配的字符串的長度。如果不匹配,則為-1。
SUBSEP 用於分隔數組元素中多個下標(索引或鍵)的字符,默認情況下為"\034",即","。
SYMTAB 一種數組,其索引是當前程序中所有定義的全局變量和數組的名稱。該數組可用於
間接訪問,以讀取或寫入變量的值。
TEXTDOMAIN AWK程序的文本域。用於查找程序字符串中的本地化翻譯。
數組變量(Arrays)
由多個元素組成的集合,通常稱之為數組。
AWK僅支持關聯數組這種數據結構,索引可以是數字或字符串。
數組中的索引包括在"[]"中括號中,並使用SUBSEP內置變量的值作為元素分隔符,默認是","。
語法:array_name[index]=value
示例:
root@localhost:~# vim awk.script
BEGIN{
x[i] = "A" # 聲明變量x是一個數組,在x中,它的第一個元素i="A",i是這個元素的鍵,"A"是值
x[j] = "B"
x[k] = "C"
if (i in x) # 判斷,如果i是x這個數組中的元素的話,則打印"hello world!"
print "hello world!"
}
root@localhost:~# awk -f awk.script
hello, world
變量類型和轉換(Variable Typing And Conversion)
變量和字段可以是數字或字符串。
被""包括的數字或字符串都將其視為是字符串,不被""包括的數字是數字。
如果想要強制將變量視為數字類型的化只需要賦值為0即可,比如:a=0;若要將其視為字符串的化,請將其與空字符串進行連接即可,比如:b=a""。
可以使用strtod(3)將字符串轉換成數字。
可以使用CONVFMT的值作為sprintf(3)的格式化字符串,將數字轉換成字符串。
示例:
root@localhost:~# vim awk.script
BEGIN{
foo = 1.131425678
CONVFMT="%.3f" # 設置數字型轉換成字符串型的格式
foo = foo "" # 將數字轉換成字符串
print foo # 打印
}
root@localhost:~# awk -f awk.script
1.131
字符串常量(String Constants)
AWK中的字符串常量是用雙引號括起來的字符序列(如:"value")。在字符串中可以識別某些轉義序列,這些轉義的字符具有特殊的作用。
\\ 將反斜杠變成普通字符,它本身具有轉義的作用。
\a "alter"字符,通常是BEL的ASCLL編碼的字符。
\b 退格。
\f 換頁。
\n 換行,新行。
\r 回車。
\t Tab。
\v 垂直標簽。
\xhex 數字。由\x后面十六進制數字字符串所代表的字符。
\ddd 由1、2、3位八進制數字序列表示的字符。
\c 字面字符c。
05. 模式、動作
AWK是一種面向行的語言。首先是模式(Patterns),然后是動作(Actions)。動作的語句包含在{}中。在一個AWK程序中,可以沒有模式或者沒有動作,但兩者不同同時都沒有。如果缺少模式,則對輸入的每條記錄執行動作。缺少動作相當於打印整個記錄,即{print}。
---
pattern{action}
---
注釋信息以#號開始,一直到行結尾。
空行可用於分隔語句。
通常語句以換行符結束,然而,以逗號結尾的行{, ?, :, &&,或者||則並不是這樣。
以do或者else結尾的行,其語句也會自動在后面的行繼續。
在其他情況下,可以通過\結尾來繼續行,在這種情況下,將忽略換行符。
多個語句可以通過;分隔放在一行上,這適用於分隔的兩個語句都是對的情況下。以;分隔的后面的語句,它不會在乎前面的語句是否執行成功,它都會執行。
模式(Patterns)
AWK的模式可以是一下模式中其中一種:
特殊模式:
BEGIN
END
BEGINFILE
ENDFILE
正則模式:
/regular expression/
關系模式:
relational expression
多關系模式:
pattern && pattern
pattern || pattern
pattern ? pattern : pattern
! pattern
范圍模式:
pattern1, pattern2
(pattern)
BEGIN和END是兩種特殊的模式,它們不需要對輸入進行測試。BEGIN在任何輸入被讀取之前被執行,END在所有輸入用盡時被執行。BEGIN和END模式不能在模式表達式中與其他模式結合使用。BEGIN和END將模式和動作合並使用BEGIN{}、END{},不能缺少動作部分。即在文件讀取開始之前和之后執行。
BEGINFILE和ENDFILE是附加的特殊模式,其主體在讀取每個命令行輸入文件的第一條記錄之前和讀取每個文件的最后一條記錄之后執行。即在文件記錄的開始和結尾執行。
對於/regular expression/模式,將為與正則表達式匹配的每個輸入記錄執行關聯語句。正則表達式與egrep中的正則表達式相同。
關系表達式可以使用下面有關操作的部分定義的任何運算符,它們通常用於測試某些字段是否匹配某些正則表達式。
&&、||、!是邏輯運算符等同於C語言中的AND、OR和NOT。
?:這個運算符與C語言中的相同。如果第一個模式(?前面的)滿足為true,則就執行第二個模式(:前面),如果為false,則執行第三個模式(:后面)。
pattern1, pattern2通常稱之為范圍模式,限定一個范圍,它匹配所有輸入的記錄,從pattern1匹配的記錄開始,一直持續到pattern2匹配的記錄結束。它不與任何其他類型的模式表達式相結合。
正則表達式(Regular Expressions)
正則表達式是egrep中發現的擴展類型。正則表達式由以下字符組成:
c 匹配非元字符c。
\c 匹配普通字符c。
. 匹配任意字符,包括換行符。
^ 匹配字符串的開頭。
$ 匹配字符串的結尾。
[abc...] 一個字符列表,匹配abc...一系列中的任意字符。
[^abc...] 否定字符列表,匹配非abc...一系列外的任意字符。
r1|r2 輪換,匹配r1或者r2。
r1r2 連接,匹配r1,然后匹配r2。
r+ 匹配一個或多個r。
r* 匹配0個或多個r。
r? 匹配0個或一個r。
(r) 分組匹配,()中的正則表達式是一個特殊字符組。
r{n} 區間表達式,n表示匹配r多少次。
r{n,} 區間表達式,n表示最少匹配r多少次。
r{n,m} 區間表達式,限定r的匹配次數。n表示最少匹配多少次,m表示最大匹配多少次。
\y 匹配空字符串,在單詞的開頭或結尾。
\B 匹配空字符串,在單詞中。
\< 匹配空字符串,在單詞的開頭。
\> 匹配空字符串,在單詞的結尾。
\s 匹配任意空字符。
\S 匹配任意非空字符。
\w 匹配任意由字母、數字或下划線組成的單詞。
\W 匹配任意非字母、數字或下划線組成的字符。
\` 匹配空字符串,在緩沖區(字符串)的開頭。
\' 匹配空字符串,在緩沖區(字符串)的結尾。
字符串常量在正則表達式中也是有效的。字符串常量有:
[:alnum:] 字母數字字符。
[:alpha:] 字母字符。
[:blank:] 空格或制表符。
[:cntrl:] 控制字符。
[:digit:] 數字字符。
[:graph:] 可打印又可見的字符。除了空格和制表符以外的所有字符。
[:lower:] 小寫字母字符。
[:print:] 可打印字符,不是控制字符的字符,
[:punct:] 標點字符(不是字母、數字、控制字符或空格字符的字符)。
[:space:] 空格字符(包括空格、制表符)。
[:upper:] 大寫字母字符。
[:xdigit:] 十六進制數字字符。
動作(Actions)
動作的語句包含在大括號{ var | Statements }
中。動作語句包含大多數語言中常見的賦值語句、條件語句和循環語句。
操作符(Operators)
AWK的操作符,按優先級從高到低的操作順序,有:
(...) 分組。
$ 字段引用。
++ -- 遞增或遞減。前綴和后綴都有。
^ 求冪(平方),也可以使用**。
+ - ! 加、減、邏輯否。
* / % 乘、除、求余。
+ - 加、減。
space 字符串連接。
| |& 為getline、print和printf提供管道I/O。
< > <= >= != == 常規的關系運算符。
~ !~ 正則表達式匹配、否定匹配。
in 數組成員身份。
&& 邏輯與。
|| 邏輯或。
?: 三元運算符,如果為true則指定:前面的語句,如果為false則執行:
后面的語句。常用於取代if語句。
= += -= *= /= %= ^= 賦值運算符。
控制語句(Control Statements)
if (condition) statement [ else statement ]
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
break
continue
delete array[index]
delete array
exit [ expression ]
{ statements }
switch (expression) {
case value|regex : statement
...
[ default: statement ]
}
I/O語句(I/O Statements)
close(file [, how]) 關閉文件、管道或協同進程。
getline 設置$0,從下一個輸入記錄;設置NF,NR,FNR,RT。geline命令
執行成功時返回1,文件結束時返回0,錯誤時返回-1,出現錯誤
時,將描述問題的字符串設置為ERRNO並返回ERRNO的值。
getline <file 設置$0,從文件的下一個記錄;設置NF,RT。
getline var 設置變量,從下一個輸入記錄;設置NR,FNR,RT。
getline var <file 設置變量,從文件的下一個記錄;設置
command | getline [var] 運行命令,將命令執行的結果轉化為$0或者變量,和RT。
command |& getline [var] 以協同進程的方式運行命令,將命令執行的結果轉化為$0或者變
量,和RT。
next 停止處理當前輸入記錄,讀取下一個輸入記錄。
nextfile 停止處理當前輸入文件,讀取下一個文件中的記錄。
print 打印當前記錄,輸入記錄從ORS的值終止。
print expr-list 打印表達式,每個表達式由OFS的值分隔,輸出記錄從ORS的值終
止。
print expr-list >file 打印表達式,從文件輸入,每個表達式由OFS的值分隔,輸出記
錄從ORS的值終止。
printf fmt, expr-list 格式化打印。
printf fmt, expr-list >file 格式化打印,打印表達式從文件中讀取。
system(cmd-line) 執行系統命令,執行完成后並返回退出狀態。
fflush([file]) 刷新與打開的輸出文件或管道文件所關聯的所有緩沖區。如果文
件丟失或為空字符串,則刷新所有打開的輸出文件和管道。
print ... >> file 將要打印的結果重定向追加到文件中。
print ... | command 將打印的結果交給管道后面的命令執行。
print ... |& command 以后台進程的方式將打印的結果交給管道后面的命令執行。
特殊文件名(Special File Names)
- 標准輸入。
/dev/stdin 標准輸入。
/dev/stdout 標准輸出。
/dev/stderr 標准錯誤輸出。
/dev/fd/n 與打開文件描述符n關聯的文件。
以下特殊的文件名可以與|&一起使用,可用於創建TCP/IP網絡連接。
/inet/tcp/lport/rhost/rport
/inet4/tcp/lport/rhost/rport
/inet6/tcp/lport/rhost/rport
/inet/udp/lport/rhost/rport
/inet4/udp/lport/rhost/rport
/inet6/udp/lport/rhost/rport
printf語句(printf Statement)
printf語句和sprintf()函數接受以下規范格式:
%c 字符。如果%c是數字,則它會被視為字符並打印出來,如果是字符串,它只打印第
一個字符。
%d, %i 十進制整數。
%e, %E 格式為[-]d.dddddde[+-]dd的浮點數。
%f, %F 格式為[-]ddd.dddddd的浮點數。
%g, %G 使用%f或者%e轉換,以較短者為准。
%o 無符號的八進制數(是一個整數)。
%u 無符號的十進制數(是一個整數)。
%s 字符串。
%x, %X 無符號的十六進制數(是一個整數)。%X使用ABCDEF,而不是abcdef。
%% %字符。
可選的,可以在%和控制字母之間添加以下參數:
count$ 在格式化的時候使用count的參數。
- 使字段左對齊。
space 對於數字轉換,正值前綴為空格,負值前綴為減號。
+ 在寬度修飾符之前使用,為數字轉換提供一個符號,使格式化的字符是一個正數。
# 對於某些控制字母使用"替換格式",對於%o,提供一個前導零。對於%x或%X提供前導0x
或0X以得出非零結果。
0 前導0充當一個標志,指示輸出應填充0,而不是空格。這只適用於數字輸出格式。
' 單引號表示在十進制數值中插入千位分隔符。
width 設置字段的寬度。
.prec 設置打印時要使用的精度的數字。對於%e、%E、%f、%F格式小數點右側的位數。
數值函數(Numeric Functions)
atan2(y, x) 返回y/x的反正切。
cos(expr) 返回expr的余弦,也就是弧度。
exp(expr) 返回expr冪函數。
int(expr) 返回expr的整數部分。
log(expr) 返回expr的自然對數。
rand() 返回一個0到1之間的隨機數N。0<=N<1。
sin(expr) 返回expr的正弦,以弧度為單位。
sqrt(expr) 返回expr的平方根。
srand([expr]) 如果將expr設置為rand()函數的話,則返回rand()的種子值0或者1,如果啥都
不設置的話,則srand()會輸出當前以秒為單位的時間戳。
字符串函數(String Functions)
asort(s [, d [, how] ]) 對數組s的值進行排序,並將排序后的值寫入到新的數據d
中,新數組的索引是1開始的。一般需要結合for語句使用。
示例:
root@localhost:~# vim awk.script
BEGIN{
a[1] = "C"
a[2] = "B"
a[3] = "F"
a[4] = "G"
for (i=1;i<=asort(a,b);i++)
print b[i]
}
root@localhost:~# awk -f awk.script
B
C
F
G
asorti(s [, d [, how] ]) 對數組s的鍵進行排序,並將排序后的鍵寫入到目標數組d中。
示例:
root@localhost:~# vim awk.script
BEGIN{
a[4] = "C"
a[3] = "B"
a[9] = "F"
a[1] = "G"
for (i=1;i<=asorti(a,b);i++)
print(b[i], a[b[i]])
}
root@localhost:~# awk -f awk.script
1 G
3 B
4 C
9 F
gensub(r, s, h [, t]) 替換字符串。在目標字符串t中搜索正則表達式r的匹配項。h
是要替換的字符位置,如果h是以g或G開頭的字符串,則將r的
所有匹配項替換為s。t是可選的,如果沒有t則默認從輸入記
錄中讀取。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "111111"
print gensub("1","x","4",string)
}
root@localhost:~# awk -f awk.script
111x11
gsub(r, s [, t]) 替換字符串。在目標字符串t中搜索正則表達式r的匹配項,將
其替換為s,並返回替換次數。直接打印gsub()返回的是替換
數,如果想要打印被替換的字符串,則請將gsub()執行的下一
行打印字符串即可。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "111111"
gsub("1","x",string)
print string
}
root@localhost:~# awk -f awk.script
xxxxxx
index(s, t) 返回字符串t在字符串s中的索引位置,不存在的話返回0。
示例:
root@localhost:~# vim awk.script
BEGIN{
print index("hello world!", "l")
}
root@localhost:~# awk -f awk.script
3
length([s]) 返回字符串的長度。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "hello world!"
print length(string)
}
root@localhost:~# awk -f awk.script
12
match(s, r [, a]) 返回正則表達式r在字符串s的位置,如果r不存在則返回0,並
設置為RSTART和RLENGTH的值。如果存在數組a,則會將正則表
達式中以()的匹配字符進行分組並將其轉換成數組a的元素。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "hello world!"
print match(string,"(.*)(w\\S*!$)",a)
print a[1]
}
root@localhost:~# awk -f awk.script
1
hello
patsplit(s, a [, r [, seps] ]) 拆分字符串。將字符串s拆分到數組a中,並返回數組a中的元
素的個數,可以使用正則表達式r匹配字段進行拆分,否則使
用空格分隔符進行拆分,可以設置seps分隔字段,則會返回匹
配該字段的數量。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "hello world hello world"
print patsplit(string,a,"\\S*") # 返回拆分后字段的數量
print a[2] # 取指定索引的字段
}
root@localhost:~# awk -f awk.script
4
world
split(s, a [, r [, seps] ]) 拆分字符串。將字符串s拆分到數組a中,並返回數組a中的元
素的個數。可以設置分隔符seps或者正則表達式r。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "hello world hello world"
print split(string,a," ") # 返回拆分后字段的數量
print a[2] # 取指定索引的字段
}
root@localhost:~# awk -f awk.script
4
world
sprintf(fmt, expr-list) 格式化字符串輸出。根據格式化字符填充對應的字段,然后返
回被新格式的字符串。
strtonum(str) 檢查字符串str,並返回它的數值。如果字符串str是以前導0
開始則將其視為八進制數,如果是以0x開頭則將其視為十六進
制數,否則它是一個十進制的數值。
sub(r, s [, t]) 與gsub()類似,但僅替換第一個匹配到字符串。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "11111-@11111-@3333"
sub("[0-9]+","heihei",string)
print string
}
root@localhost:~# awk -f awk.script
heihei-@11111-@3333
substr(s, i [, n]) 截取字符串。返回在字符串s中從位置i開始到位置n結束的字
符串。
示例:
root@localhost:~# vim awk.script
BEGIN{
string = "11111-@22222-@3333"
print substr(string,7,6)
}
root@localhost:~# awk -f awk.script
@22222
tolower(str) 大小寫轉換。將字符串str中的大寫字符轉換成小寫字符后輸
出。
toupper(str) 大小寫轉換。將字符串str中的小寫字符轉換成大寫字符后輸
出。
時間函數(Time Functions)
由於AWK程序的主要用途之一是處理包含時間戳信息的日志文件,GAWK提供以下獲取時間戳和格式化的功能函數。
mktime(datespec) 將datespec轉換成與systime()相同格式的時間戳。datespec
是格式為YYYY MM DD HH MM SS DST 的字符串。這將返回以秒
為單位的時間戳。
示例:
root@localhost:~# vim awk.script
BEGIN{
print mktime("2021 01 25 18 48 00")
}
root@localhost:~# awk -f awk.script
1611571680
strftime([format [, timestamp[, utc-flag]]])
根據指定的時間格式,返回對應的時間。如果指定了時間戳
timestamp,則返回對應時間戳的時間。如果設置UTC標志utc-
flag的值為非0時,則輸出的時間格式時UTC。
示例:
root@localhost:~# vim awk.script
BEGIN{
print strftime("%Y-%m-%d %H:%M:%S",1611571885)
}
root@localhost:~# awk -f awk.script
2021-01-25 18:51:25
systime() 返回當前系統的時間戳,以秒為單位。
位操作函數(Bit Manipulations Functions)
and(v1, v2 [, ...])
compl(val)
lshift(val, count)
or(v1, v2 [, ...])
rshift(val, count)
xor(v1, v2 [, ...])
類型函數(Type Function)
isarray(x) 如果x是一個數組,則返回true,否則返回false。
國際化函數(Internationalization Functions)
bindtextdomain(directory [, domain])
dcgettext(string [, domain [, category]])
dcngettext(string1, string2, number [, domain [, category]])
用戶自定義函數(User-Defined Functions)
用戶可以根據自己的需求自定義函數,並在其他地方應用。在函數中可以使用return語句返回執行后的結果。
語法:function name(parameter list) { statements }
示例:
root@localhost:~# vim awk.script
# 這是一個自定義的加法函數
function addition(a, b) # 創建函數
{
result = a + b
return result # 返回結果
}
BEGIN{
print addition(1,2) # 引用函數
}
root@localhost:~# awk -f awk.script
3
退出狀態(Exit Status)
可以使用exit語句設置AWK程序的退出狀態。
如果程序執行沒有問題,GAWK通常使用常量EXIT_SUCCESS的值退出,這通常是0。
如果發生錯誤,GAWK會使用常量EXIT_FAILURE的值退出,這通常是1。
如果由於致命錯誤而退出,則退出狀態為2。
06. 常用示例
查看最近登錄用戶
[root@localhost ~]# last -n 5 | awk '{print $1}'
root
root
root
reboot
root
查看系統中有哪些用戶
[root@localhost ~]# cat /etc/passwd | awk -F ":" '{print $1}'
root
bin
daemon
adm
lp
sync
查看系統有哪些用戶,以及查看是否允許用戶系統登錄
[root@localhost ~]# cat /etc/passwd | awk -F ":" '{print $1"\t"$7}'
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
查看內存空閑值大小是否超過500M,如果是則打印出來
[root@localhost ~]# free -m |head -n 2 |grep -n 2|awk '{if($4>500){print $4}}'
593
獲取CPU使用率TOP10的進程,並限制每行進程的字符長度
[root@localhost ~]# ps aux --sort=-%cpu|head -n 10 |awk '{print substr($0,0,120)}')
顯示空間使用率大於80%的硬盤
[root@localhost ~]# df -Th |grep -v '^Filesystem'|awk '{split($6,a,"%");if(a[1]>80){print $0}}'