天天看點

shell --- awk規範 系統總結

文章目錄

  • ​​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​

    ​開頭的字段
  • shell --- awk規範 系統總結
  • 使用x++,可以列印行号
  • shell --- awk規範 系統總結

awk表達式

指派操作符

  • ​=​

    ​最常使用的操作符(等号前後可以增加空格)
  1. ​var1 = "name"​

  2. ​var2 = "hello" "world"​

    ​ 指派多個運算符
  3. ​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​

    ​輸出字段分隔符
  • shell --- awk規範 系統總結
  • ​RS​

    ​​記錄分隔符,行之間的合并

    将每一行的記錄分隔符​

    ​\n​

    ​設定為​

    ​:​

    ​,則每當遇到​

    ​:​

    ​,即代表一行

    ​head -5 /etc/passwd | awk 'BEGIN{RS=":"}{print $0}'​

  • ​NR​

    ​​和​

    ​FNR​

    ​行數

    當輸入為多個檔案時,​

    ​FNR​

    ​可以重排多個檔案,​

    ​FR​

    ​則都按照一個檔案的行号排列
  • shell --- awk規範 系統總結
  • ​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​

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 變量
}