一、使用變量
gawk支持兩種變量
- 內建變量
- 自定義變量
1.1 內建變量
1.1.1 字段和記錄分隔符變量
數據字段變量允許使用美元符號 $ 和 位置來引用對應的字段。 $1 對應第一個數據字段,$2對應第二個數據字段,以此類推。
數據字段用字段分隔符劃定。默認情況下,字段分隔符是一個空白字符(空格或制表符)。可以通過 -F選項修改字段分隔符。也可以使用特殊的內建變量FS修改字段分隔符。
有一組內建變量可以控制輸入和輸出數據中字段和記錄的處理方式:
變 量 | 描 述 |
---|---|
FIELDWIDTHS | 由空格分隔的一串數字,定義了每個數據字段的確切寬度 |
FS | 輸入字段分隔符 |
RS | 輸入記錄分隔符 |
OFS | 輸出字段分隔符 |
ORS | 輸出記錄分隔符 |
$ cat < data1
header line
data line 1
End of data line#默認情況
$ gawk '{print $1,$2}' data1
header line
data line
End of#1、OFS測試$ gawk 'BEGIN{OFS="|-|"}
{print $1,$2}' data1
header|-|line
data|-|line
End|-|of#2、ORS測試$ gawk 'BEGIN{ORS="|-|"}
{print $1,$2}
END{print "\n"}' data1
header line|-|data line|-|End of|-|
默認輸出字段分隔符是空格,第1個例子將輸出字段分隔符換成了"|-|“。
默認輸出記錄分隔符是換行,第2個例子將輸出記錄分隔符換成了”|-|"。
FIELDWIDTHS會根據提前設置好的字段寬度來劃分字段。
下面這個例子將固定格式的時間劃分成 年、月、日、時、分。
$ cat <data2
202401011015
202402020900
202403030130$ gawk 'BEGIN{
FIELDWIDTHS="4 2 2 2 2 2"}
{print $1,$2,$3,$4,$5}' data2
2024 01 01 10 15
2024 02 02 09 00
2024 03 03 01 30
FS默認為空白符,RS默認為換行符。也就是說gawk默認一行為一條記錄。但有時一行數據是一個字段,多行數據組成一條記錄。這時可以將FS設置成\n,將RS設置成空字符串。
$ cat <data3
zhangsan
17
haerbinlisi
20
beijing$ gawk 'BEGIN{FS="\n";RS=""}
{print"name:"$1,"age:"$2,"city:"$3}' data3
name:zhangsan age:17 city:haerbin
name:lisi age:20 city:beijing
1.1.2 數據變量
除了字段和記錄分隔符變量外,gawk還提供了其他一些變量幫助了解數據的變化。
變量 | 描述 |
---|---|
ARGC | 命令行參數的數量 |
ARGIND | 當前處理的文件在ARGV中的索引 |
ARGV | 包含命令行參數的數組 |
CONVFMT | 數字的轉換格式(參見printf語句),默認為%.6g |
ENVIRON | 當前環境變量及其值組成的關聯數組 |
ERRNO | 當讀取或關閉輸入文件發生錯誤時的系統錯誤號 |
FILENAME | 用作gawk輸入的數據文件的名稱 |
FNR | 當前數據文件中已處理的記錄數 |
IGNORECASE | 非0表示忽略大小寫 |
NF | 數據文件中的字段總數 |
NR | 已處理的輸入記錄數 |
OFMT | 數字的輸出格式。默認值為%.6g。以浮點數或科學計數法表示,以較短者為準,最多是使用6位小數 |
RLENGTH | 由match函數所匹配的子串長度 |
RSTART | 由match函數所匹配的子串的起始位置 |
下面測試幾個常用的變量
#ARGC:命令行參數的數量
#ARGV:當前處理的文件在ARGV中的索引
$ gawk 'BEGIN{print ARGC,ARGV[0],ARGV[1],ARGV[2]}' data1 data2
3 gawk data1 data2#ENVIRON:當前環境變量及其值組成的關聯數組
$ gawk 'BEGIN{print ENVIRON["HOME"]}'
/home/ubuntu#FILENAME :用作gawk輸入的數據文件的名稱
$ gawk 'END{print FILENAME}' data1
data1
$ cat < data1
header line
data line 1
End of data line$ cat <data2
202401011015
202402020900
202403030130#NR:已處理的輸入記錄數
#FNR:當前數據文件中已處理的記錄數
#NF:數據文件中的字段總數
#$NF:最后一個字段的值
$ gawk '{print "NR="NR,"FNR="FNR,"NF="NF,"$NF="$NF}' data1 data2
NR=1 FNR=1 NF=2 $NF=line
NR=2 FNR=2 NF=3 $NF=1
NR=3 FNR=3 NF=4 $NF=line
NR=4 FNR=1 NF=1 $NF=202401011015
NR=5 FNR=2 NF=1 $NF=202402020900
NR=6 FNR=3 NF=1 $NF=202403030130
NR=7 FNR=4 NF=0 $NF=
1.2 自定義變量
gawk的自定義變量由任意個字母、數字和下劃線組成,但不能以數字開頭。
gawk自定義變量區分大小寫。
1.2.1 在腳本中為變量賦值
$ gawk 'BEGIN{test="this is a test.";print test}'
this is a test.$ gawk 'BEGIN{test=100;print test*(test-1)}'
9900$ gawk 'BEGIN{test=100;print test^2}'
10000
1.2.2 在命令行中給變量賦值
$ cat <data1
header line
data line 1
End of data line$ gawk '{print $field}' field=1 data1
header
data
End$ gawk '{print $field}' field=2 data1
line
line
of
這個例子通過在命令行中給變量賦值,可以顯示不同的字段。
這個特性可以在不改變腳本代碼的情況下改變腳本的行為。
使用命令行參數定義變量有一個問題:設置變量后,這個變量在BEGIN模塊不可用
如下:
$ gawk 'BEGIN {print "field="field}' field=3 data1
field=
可以用 -v選項解決這個問題。-v選項允許在BEGIN之前定義變量。
$ gawk -v field=3 'BEGIN {print "field="field}' field=3 data1
field=3
二、處理數組
數組用于單個變量存儲多個值,gawk語言使用關聯數組提供數組功能。類似c++中的unorder_map。
2.1 定義數組變量
可以用賦值語句定義數組變量。格式如下;
var[index]=element
var:數組變量名
index:索引
element:索引對應的值
$ gawk 'BEGIN{arr["name"]="lilei";arr["age"]=20;
print arr["name"],arr["age"]}'
lilei 20
2.2 遍歷數組變量
格式:
for index in array
{
?statement
}
for語句每次循環時會把下一個數組元素的索引賦值給index。
$ gawk 'BEGIN{arr["name"]="lilei";arr["age"]=20;
for (ind in arr)
{
print "arr["ind"]="arr[ind]
}}'
arr[age]=20
arr[name]=lilei
索引沒有固定的返回順序。
2.3 刪除數組變量
從關聯數組中刪除數據需要使用 delete 命令;
delete array[index]
下面使用delete命令的例子
$ cat < gawk_cmd
BEGIN {arr["name"]="lilei";arr["age"]=20;arr["city"]="haerbin";for (ind in arr){print "arr["ind"] :" arr[ind];}delete arr["age"];print "---------"for (ind in arr){print "arr["ind"] :" arr[ind];}
}$ gawk -f gawk_cmd
arr[age] :20
arr[city] :haerbin
arr[name] :lilei
---------
arr[city] :haerbin
arr[name] :lilei
每行代碼后面的分號 ( ; ) 寫不寫都行。
三、 使用模式
3.1 正則表達式
sed 只支持基礎正則表達式(BRE),gawk支持基礎正則表達式(BRE) 和擴展正則表達式(ERE)。
下面的第1個例子輸出張三的年齡,第2個例子輸出年齡在20~30之間的人的名字。
$ cat <data3
zhangsan
17
haerbinlisi
20
beijing$ gawk 'BEGIN{FS="\n";RS=""}
/zhangsan/{print $2}' data3
17$ gawk 'BEGIN{FS="\n";RS=""}
/2./{print $1}' data3
lisi
3.2 匹配操作符
匹配操作符 (~) 使用格式:
數據字段 ~ /正則表達式/
和上面的例子相同,下面第1個例子輸出zhangsan的年齡,第2個例子輸出年齡在20~30之間的人的名字。
$ gawk 'BEGIN{FS="\n";RS=""}
$1 ~ /zhangsan/{print $1,$2,$3}' data3
zhangsan 17 haerbin$ gawk 'BEGIN{FS="\n";RS=""}
$2 ~ /^2.$/{print $1,$2,$3}' data3
lisi 20 beijing
3.3 數學表達式
處理正則表達式,gawk還可以在匹配模式中使用數學表達式。
可以使用任何常見的數學表達式:
操作符 | 描述 |
---|---|
== | 等于 |
<= | 小于等于 |
< | 小于 |
> | 大于 |
>= | 大于等于 |
還是相同的例子,輸出張三的年齡
$ cat <data3
zhangsan
17
haerbinlisi
20
beijing$ gawk 'BEGIN{FS="\n";RS=""}
$1=="zhangsan"{print "age="$2}' data3
age=17
四、結構化命令
gawk 中的結構化命令和 c語言 中的分支和循環結構基本一致。
4.1 if語句
輸出年齡是否大于18歲
$ cat <data3
zhangsan
17
haerbinlisi
20
beijing$ cat < gawk_cmd
BEGIN {FS="\n"RS=""print "Begin"
}{cmp=""age=18if ($2 <= age){cmp=" less than "}else{cmp=" greater than "}print $1 cmp,age
}END{print "End of file"
}$ gawk -f gawk_cmd data3
Begin
zhangsan less than 18
lisi greater than 18
End of file
4.2 while 語句
格式:
while (condition)
{
?statements
}
下面例子輸出某次跳遠比賽各個選手的平均成績。
$ cat < data1
5.5 6.5 7.5
6.6 6.5 6.5
6.6 7.5 5.9$ cat < gawk_cmd
BEGIN {print "Begin"
}{i=1sum=0.0while (i <= NF){sum+=$ii++}print sum/NF
}END{print "End of file"
}$ gawk -f gawk_cmd data1
Begin
6.5
6.53333
6.66667
End of file
4.3 do-while語句
格式:
do
{
?statements
}
while (condition)
do-while 與 while 唯一區別是 do-while保證statements會在條件被求值之前至少執行一次。
4.4 for語句
格式:
for (變量賦值; condition; 迭代處理)
{
?statements
}
下面使用for語句計算跳遠比賽的平均成績。
$ cat < gawk_cmd
BEGIN {print "Begin"
}{sum=0.0for(i=1;i<=NF;i++){sum+=$i}print sum/NF
}END{print "End of file"
}$ gawk -f gawk_cmd data1
Begin
6.5
6.53333
6.66667
End of file
五、格式化打印
5.1 printf 命令
gawk中的printf命令和 C語言 中的printf函數一樣。
格式:
printf “format string”,var1,var2…
控制字母 | 描述 |
---|---|
c | 數字作為ASCII字符顯示 |
d和i | 顯示整數值 |
e | 用科學計數法顯示數字 |
f | 顯示浮點數 |
g | 用科學計數法或浮點數顯示(較短的格式有限) |
o | 顯示八進制 |
s | 顯示字符串 |
x | 顯示十六進制 |
X | 顯示十六進制,但用大寫字母A-F |
#將輸入數據當做字符串
$ echo "200.33333"| gawk '{printf "%s\n",$1}'
200.33333#將輸入數據當作小數并保留兩位小數
$ echo "200.33333"| gawk '{printf "%2.2f\n",$1}'
200.33#將輸入數據當作整數,并且至少輸出5位,不足5位向前補0
$ echo "200.33333"| gawk '{printf "%05d\n",$1}'
00200
六、自定義函數
6.1 定義函數
格式:
function name ([variables])
{
? statements
}
6.2 使用函數
使用自定義函數計算平均成績
$ cat < gawk_cmd
function average(s1,s2,s3)
{return (s1 + s2 + s3)/3
}BEGIN {print "Begin"}{printf "average scores:%.2f\n",average($1,$2,$3)
}END{print "End of file"
}$ gawk -f gawk_cmd data1
Begin
average scores:6.50
average scores:6.53
average scores:6.67
End of file
6.3 函數庫
也可以把常用的函數放到一個文件中,封裝成函數庫。
$ cat < lib_func
function average(s1,s2,s3)
{return (s1 + s2 + s3)/3
}$ cat < lib_func
function average(s1,s2,s3)
{return (s1 + s2 + s3)/3
}
ubuntu@VM-8-14-ubuntu:~$ cat < gawk_cmdBEGIN {print "Begin"
}{printf "average scores:%.2f\n",average($1,$2,$3)
}END{print "End of file"
}$ gawk -f lib_func -f gawk_cmd data1
Begin
average scores:6.50
average scores:6.53
average scores:6.67
End of file