文章目錄
- awk和sed的差別
- awk腳本的流程控制
- awk 記錄和字段
- 字段的引用
- awk表達式
- 指派操作符
- 算數操作符
- 系統變量(awk本身自定義的系統變量)
- 關系操作符
- 布爾操作符
- awk 條件和循環
- 條件語句
- 循環
- awk 的數組
- 數組的定義
- 數組的周遊
- 删除數組
- 舉例,編寫awk腳本檔案`avg.awk`
- 指令行參數數組
- 複雜數組的使用案例
- awk函數
- 算數函數
- 字元串函數
- 自定義函數
awk和sed的差別
- awk更像是腳本語言
- awk用于“比較規範”的文本處理,用于統計數量并輸出指定字段
- 使用sed 将不規範的文本,處理為“比較規範的文本”
awk腳本的流程控制
- 輸入資料前 例程 BEGIN{},相當于預處理,進行變量定義
- 主輸入循環{} ,一般隻寫主輸入循環
- 所有檔案讀取完成 例程END{}
awk 記錄和字段
- 每一行稱為 akw記錄
- 使用空格、制表符分隔開的單詞稱為字段
- 可以自己指定分隔的字段
字段的引用
- awk中使用$1,$2,$3…$n表示每隔字段
awk '{print $1,$2,$3}' filename
- awk 可以使用-F選項改變字段分隔符
awk -F, '{print $1, $2, $3}' filename
分隔符可以使用正規表達式
使用單引号作為分隔符,讀取以
開頭的字段menu
- 使用x++,可以列印行号
awk表達式
指派操作符
-
最常使用的操作符(等号前後可以增加空格)=
-
var1 = "name"
-
指派多個運算符var2 = "hello" "world"
-
var3 = $1
-
其他指派運算符
++ , -- , +=, -=, *=, /=, %=, ^=
算數操作符
-
+, -, *, /, %, ^
系統變量(awk本身自定義的系統變量)
-
和FS
系統變量,OFS
OFS
表示輸出的字段分隔符
awk讀取每一行的内容之前,都會先讀取
和FS
OFS
表示的分隔符,輸入時進行字段的提取,輸出時根據OFS增加分隔符
舉例如下:
head -5 /etc/passwd | awk -F ":" '{print $1}'
使用-F來分隔就等價于
,通過head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print $1}'
BEGIN
讀入之前,設定好字段分隔符。
增加
輸出字段分隔符OFS
-
RS
記錄分隔符,行之間的合并
将每一行的記錄分隔符
設定為\n
,則每當遇到:
:
,即代表一行
head -5 /etc/passwd | awk 'BEGIN{RS=":"}{print $0}'
-
和NR
FNR
行數
當輸入為多個檔案時,
可以重排多個檔案,FNR
則都按照一個檔案的行号排列FR
-
字段數量,最後一個字段内容可以用NF
$NF
取出字段内容
head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print NF}'
,輸出每一行的字段個數
,輸出最後一個字段的内容head -5 /etc/passwd | awk 'BEGIN{FS=":"}{print $NF}'
關系操作符
<, >, <=, >=, ==, !=, ~, !~
布爾操作符
&&, ||, !
awk 條件和循環
條件語句
- 條件語句使用
開頭,根據表達式結果判斷執行哪一條語句if
if(表達式)
awk 語句1
[else
awk 語句2
]
- 如果有多個語句需要執行,可以使用{}将多個語句括起來
循環
-
循環while
while (表達式)
awk 語句1
-
循環do
do{
awk 語句1
}while(表達式)
-
循環for
for(初始值;循環判斷條件;累加)
awk 語句1
-
使用for進行求和,并取平均值
cat kpi.txt | awk '{sum=0;for(c=2;c<=NF;++c) sum+=$c;print sum/(NF-1)}'
-
影響控制的其他語句
break
continue
awk 的數組
主要為了對awk進行多行關聯,多行之間進行通信
數組的定義
數組:一組有某種關聯的資料(變量),通過下标依次通路
數組名[下标]=值
下标可以使用數字,也可以使用字元串。
PS:即使使用的是數字,awk也會将其當作字元串或者字元來處理
數組的周遊
for (變量 in 數組名)
#使用 數組名[變量] 的方式依次對每個數組的元素進行操作
删除數組
delete 數組[下标]
舉例,編寫awk腳本檔案 avg.awk
avg.awk
awk '{sum=0;\
for(c=2;c<=NF;++c)\
sum+=$c;\
avg[$1]=sum/(NF-1)}\
END{\
for(user in avg)
sum2+=avg[user];
print sum2/NR}' \
kpi.txt
加載awk腳本檔案
awk -f avg.awk kpi.txt
指令行參數數組
指令行參數數組:
ARGC
參數個數 和
ARGV
代表的參數内容
主要用來輔助awk的腳本使用
編輯
arg.awk
BEGIN{
for(x = 0;x < ARGC;x ++)
print ARGV[x] #列印每個參數内容
print ARGC #列印參數個數
}
執行指令
awk -f arg.awk 11 22 33
輸出如下:
awk #第0個參數,指令名稱
11
22
33
4 #總共四個參數(目前指令也會被記錄進去)
複雜數組的使用案例
編輯
result.awk
,用來進行總分,平均分、高于且低于平均分人數統計、分數評級、各個級别人數統計,該資料記錄在
kpi.txt
{
sum = 0
for(c = 2; c <= NF; c++)
sum += $c
avg[$1] = sum / (NF - 1)
if(avg[$1] >= 80) #統計每個人的評級
level = "S"
else if(avg[$1] >=70)
level = "A"
else if(avg[$1] >= 60)
level = "B"
else
level = "C"
print $1,avg[$1],level
letter_all[level] ++ #關聯數組,統計各個評級的人數
}
END {
for(usr in avg)
sum2 += avg[usr]
avg_all = sum2 / NR #所有人的平均成績
print "avg_all is :",avg_all
for(usr in avg) #計算超過以及小于平均成績的人數
if(avg[usr] >= avg_all)
up++
else
down++
print "biger than avg_all",up
print "less than avg_all",down
print "S:",letter_all["S"]
print "A:",letter_all["A"]
print "B:",letter_all["B"]
print "C:",letter_all["C"]
}
運作
awk -f result.awk kpi.txt
其中
kpi.txt
内容如下:
user1 72 56 83 91
user2 55 67 45 89
user3 90 87 85 83
user4 56 57 99 95
user5 55 60 64 32
最終輸出如下:
user1 75.5 A
user2 64 B
user3 86.25 S
user4 76.75 A
user5 52.75 C
avg_all is : 71.05
biger than avg_all 3
less than avg_all 2
S: 1
A: 2
B: 1
C: 1
awk函數
算數函數
-
和 sin()
cos()
-
int()
awk 'BEGIN{pi=3.14;print int(pi)}'
-
僞随機數 和 rand()
srand()
重新擷取種子 0-1之間
awk 'BEGIN{srand();print rand()}'
字元串函數
-
字元串替換gsub(r,s,t)
-
字元串替換sub(r,s,t)
-
字元串替換substr(r,s,t)
-
字元串分割split(s,a,sep)
-
字元串比對match(s,r)
-
字元串長度length(s)
-
index(s,t)
通過
man awk
搜尋函數名稱,可以看到具體函數的功能以及詳細用法
自定義函數
函數定義的位置,寫在
BEGIN
,
{}
,
END
之外
function 函數名(參數){
awk 語句
return awk 變量
}