awk既是一個(gè)shell工具,也是一門編程語(yǔ)言,linux和osx下都可以直接用,windows下有g(shù)awk(下載鏈接)。
以下內(nèi)容參考mawk用戶手冊(cè)(man awk
),可能與標(biāo)準(zhǔn)awk語(yǔ)言有出入
一、工作原理
- awk掃描輸入的每一行(記錄分隔符
RS
, record separator), - 每行會(huì)被分隔成若干個(gè)域(域分隔符
FS
, field separator), - 根據(jù)
pattern
匹配每一行, - 如果匹配就執(zhí)行
action
二、awk解釋器
程序文件
- 短的程序內(nèi)容可以用單引號(hào)包括,直接在命令行中運(yùn)行;
awk '{print $1}' text_file
- 長(zhǎng)的程序文件可以通過(guò)
-f
參數(shù)指定路徑。
awk -f awk_program_file text_file
文本文件
- awk可以接收多個(gè)文件路徑作為輸入
- awk可以接收管道輸出作為輸入
- 如果沒(méi)有指定上面兩者,awk對(duì)標(biāo)準(zhǔn)輸出進(jìn)行處理
mawk命令行
mawk [-W option] [-F value] [-v var=value] [--] 'program text' [file ...]
mawk [-W option] [-F value] [-v var=value] [-f program-file] [--] [file ...]
三、awk編程語(yǔ)言
1). 程序結(jié)構(gòu)
awk程序包含若干pattern {action}
序列和函數(shù)定義。
-
pattern
和action
不能同時(shí)省略
-
pattern
可以省略,如果省略,默認(rèn)匹配成功 -
action
可以省略,如果省略,默認(rèn)為print
-
pattern
可以為
-
BEGIN
匹配文本文件開(kāi)始位置, 其action
不能為空 -
END
匹配文本文件結(jié)束位置,其action
不能為空 -
expression
單個(gè)表達(dá)式 -
expression, expression
多個(gè)表達(dá)式
- 其他語(yǔ)句
- 語(yǔ)句結(jié)束符為新行或者分號(hào);
- 一個(gè)語(yǔ)句塊由大括號(hào)包圍;
- 一條語(yǔ)句可以使用反斜杠進(jìn)行跨行;
- 注釋由
#
開(kāi)頭
- 流程控制語(yǔ)句
if ( expr ) statement
if ( expr ) statement else statement
while ( expr ) statement
do statement while ( expr )
for ( opt_expr ; opt_expr ; opt_expr ) statement
for ( var in array ) statement
continue
break
2). 數(shù)據(jù)類型
awk有兩種基本數(shù)據(jù)類型:
- 數(shù)字型
- 可以為整數(shù)
2, -2
- 可以為小數(shù)
0.5
- 可以為科學(xué)表示法數(shù)字
0.2e8 1.2E5
所有數(shù)字內(nèi)部由浮點(diǎn)數(shù)進(jìn)行表示和計(jì)算,
true
表示為1.0
- 字符型
- 字符串用雙引號(hào)包括
"a string"
- 特殊字符可以由反斜杠\轉(zhuǎn)義
3). 正則表達(dá)式
正則表達(dá)式由斜杠包括/r/
;
- 匹配操作符
~
右側(cè)可以為一個(gè)表達(dá)式 - 非匹配操作符
!~
右側(cè)可以為一個(gè)表達(dá)式
pattern-action對(duì)可以這樣表示:
/r/ {action}
或$0 ~ /r/ {action}
4). 記錄和域
- 每次記錄(record, 行)存儲(chǔ)在域(field)
$0
中, - 每行被分隔為多個(gè)域,分別存在
$1, $2, ... $NF
中, -
NF
(number of fields)被設(shè)置為域的數(shù)量, -
NR
和FNR
遞增
5). 表達(dá)式和操作符
基本表達(dá)式
- 數(shù)字常量
- 字符串常量
- 變量
- 域
- 數(shù)組
- 函數(shù)調(diào)用
變量、數(shù)組和函數(shù)命名可以為字符、數(shù)字、下劃線,不能以數(shù)字開(kāi)頭。
變量不用聲明,第一次使用會(huì)被初始化為null
操作符:
assignment = += -= *= /= %= ^=
conditional ? :
logical or ||
logical and &&
array membership in
matching ~ !~
relational < > <= >= == !=
concatenation (no explicit operator)
add ops + -
mul ops * / %
unary + -
logical not !
exponentiation ^
inc and dec ++ -- (both post and pre)
field $
6). 數(shù)組
awk可以表示一維數(shù)組array[expr]
, expr
會(huì)被轉(zhuǎn)換為字符串類型。
- 成員檢查
expr in array
在返回1
,否則返回0
- 下標(biāo)遍歷
for(var in array)
- 刪除成員
delete array[expr]
- 多維數(shù)組
array[expr1, expr2]
等于array[expr1 SUBSEP expr2]
- 成員測(cè)試
if( (i, j) in array) print array[i, j]
- 成員測(cè)試
7). 內(nèi)建變量
變量名 | 含義 | 縮寫(xiě) |
---|---|---|
ARGC |
參數(shù)數(shù)量 | |
ARGV |
參數(shù)數(shù)組 | |
CONVFMT |
內(nèi)部數(shù)字轉(zhuǎn)字符串格式,默認(rèn)為%.6g
|
|
ENVIRON |
環(huán)境變量數(shù)組 | |
FILENAME |
當(dāng)前輸入文件 | |
FNR |
當(dāng)前記錄編號(hào) | file record number |
FS |
域分隔符 | field separator |
NF |
域數(shù)量 | number of fields |
NR |
當(dāng)前記錄編號(hào) | record number |
OFMT |
數(shù)字輸出格式, 默認(rèn)%.6g
|
output format |
OFS |
輸出域分隔符,默認(rèn)空格 | output field separator |
ORS |
輸出記錄分隔符 默認(rèn)\n
|
output record separator |
RLENGTH |
最近一次match調(diào)用的長(zhǎng)度 | |
RSTART |
最近一次match調(diào)用得到的下標(biāo) | |
RS |
輸入記錄分隔符 | record separator |
SUBSEP |
多維數(shù)組下標(biāo)分隔符,默認(rèn)\034
|
subscript separator |
8). 內(nèi)建函數(shù)
字符串函數(shù) | 含義 | 算術(shù)函數(shù) | 含義 |
---|---|---|---|
gsub(r, s[, t]) |
字符串替換 | atan2(y, x) |
|
index(s, t) |
返回子串位置 | cos(x) |
|
length(s) |
返回字符串長(zhǎng)度 | exp(x) |
|
match(s, r) |
返回首個(gè)匹配位置 | int(x) |
取整 |
split(s, A[, r]) |
分隔s到A數(shù)組 | log(x) |
|
sprintf(format, expr-list) |
rand() |
0-1之間隨機(jī)數(shù) | |
sub(r, s[, t]) |
替換一次 | sin(x) |
|
substr(s, i[, n]) |
返回子串 | sqrt(x) |
|
tolower(s) |
返回小寫(xiě)形式 | srand([expr]) |
根據(jù)種子隨機(jī) |
toupper(s) |
返回大寫(xiě)形式 |
9). 輸入輸出
輸出語(yǔ)句:
print
print expr1, expr2, ..., exprn
printf format, expr-list
輸入語(yǔ)句:
-
getline
讀取一行 -
getline < file
從文件讀取一行 -
getline var
讀到var -
getline var < file
從文件讀到var -
command | getline
從管道讀取一行 -
command | getline var
從管道讀到var
其他語(yǔ)句:
-
close(expr)
關(guān)閉文件 -
fflush(expr)
刷新輸出文件 -
system(expr)
執(zhí)行expr
10). 自定義函數(shù)
格式:
function name(args) { statements }
可以有返回值,但不必須:
return opt_expr
傳入?yún)?shù)和局部變量參數(shù)之間使用多個(gè)空格分隔(慣例)
11). 字符串、記錄、文件分隔
同一種分隔算法:split(expr, A, sep)
12). 多行記錄
設(shè)置RS
13). 程序執(zhí)行
-
ARGC
被設(shè)置為命令行參數(shù)數(shù)目,ARGV[0]
被設(shè)置為awk解釋器,ARGV[i]
被設(shè)置為其余命令行參數(shù) - 然后
BEGIN
語(yǔ)句塊被依次執(zhí)行。如果只有BEGIN
語(yǔ)句,程序結(jié)束;否則打開(kāi)輸入流。如果ARGC
=1,輸入流被設(shè)置為stdin
。然后ARGV[i]
將被作為文件參數(shù)檢查。 - 命令行參數(shù)可分為三類:文件參數(shù)、賦值參數(shù)、空字符串。賦值參數(shù)格式為
var=string
。如果ARGV[i]
可能是個(gè)文件參數(shù),如果為空就跳過(guò);如果是賦值參數(shù),就會(huì)設(shè)置var的值,然后跳到下個(gè)參數(shù);否則ARGV[i]
作為輸入打開(kāi)。如果打開(kāi)失敗,程序結(jié)束,返回錯(cuò)誤碼2。如果沒(méi)有參數(shù)是文件參數(shù),輸入從stdin
獲取。在BEGIN
中getline
會(huì)打開(kāi)輸入,-
表示stdin
。 - 輸入流打開(kāi)之后,每條輸入記錄都會(huì)與
pattern
進(jìn)行匹配。如果匹配,相關(guān)的action
就會(huì)執(zhí)行。表達(dá)式模式為true
時(shí)才匹配。BEGIN
匹配在任何輸入讀取之前匹配,END
在所有輸入讀取結(jié)束之后匹配。范圍表達(dá)式expr1, expr2
匹配兩個(gè)表達(dá)式分別匹配的行之間所有行,并包含這兩個(gè)匹配行。 - 當(dāng)輸入流的文件結(jié)束時(shí),其余的命令行參數(shù)會(huì)被檢查是否是文件參數(shù),如果有就會(huì)被打開(kāi),重復(fù)上一步驟。如果沒(méi)有,
END
模式會(huì)被匹配,所有的END
的action
都會(huì)被執(zhí)行。 -
pattern {action}
層次的程序流程可以被一下語(yǔ)句改變:next
exit opt_expr
其他參考
酷殼
man awk