AWK的使用

一、AWK介紹

   Linux文本處理工具三劍客:grep、sed和AWK。其中grep是一種文本過濾工具,sed是文本行編輯器,而AWK是一種報表生成器,就是對文件進行格式化處理,這裏的格式化不是文件系統的格式化,而是對文件內容進行各種“排版”,進而格式化顯示
   在Linux之上我們使用的GUN awk ,簡稱gawk,並且gawk其實awk的鏈接文件,因此在系統上使用awk和gawk都是一樣的。我們通過mangawk可以獲得gawk的相關功能說明----------- gawk-pattern scanning and processing language(模式掃描及各種處理語言),gawk是一種過程式編程語言,gawk還支持條件判斷,數組、循環等各種編程語言中所有可以使用的功能,因此我們還可以吧gawk稱爲一種監本語言解釋器。

二、AWK基本用法

   awk 在處理文本時也是一次讀取一行文本,文件的每一行稱爲記錄,由分隔符分隔的字段(域)標記爲$1,$2...$n,稱爲域標識,$0爲所有域,和shell中變量$符含義不同,然後根據輸入分隔符(默認爲空格字符)進行切片,切成n段,然後將每一片都賦予awk內部的一個變量當中這些$1,$2等等一直到最後一個,awk就可以對這些片段進行處理,比如某一段、特定段,比如計數、運算等

 1、awk的運行方式有3種

  1)awk命令行

   #awk

  2)awk 程序文件

   # awk -f /PATH/AWK_SCRIPT

  3)awk腳本

   #!/bin/awk -f

2、awk的基本用法

  awk [option] ‘program’ file1 file2
   Option:選項
    -F[] :指明輸入時用到的字段分隔符,例:-F:
    -v var=value: 自定義變量,例:-v var=123
    -f /PATH/AWK_SCRIPT:指定awk程序的文件
   Program:prattern{action statements;}
    awk編程語言,通常由BEGIN語句塊、能夠使用模式匹配的通用語句塊、END,共3部分組成。Program通常是被單引號或雙引號中
    parttern部分決定動作語句何時觸發及觸發事件
      BEGIN:在讀取文件之前執行
      END:在讀取文件之後執行
    Action statements:動作語句,可以是由多個語句組成,各語句之間使用分號分隔“;”
      print:換行打印
      printf:不換行打印

 3、 Awk工作原理

  第一步:執行BEGIN{action;… }語句塊中的語句
  第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這 個過程,直到文件全部被讀取完畢。
  第三步:當讀至輸入流末尾時,執行END{action;…}語句塊
   BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個 可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常 可以寫在BEGIN語句塊中
   END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如 打印所有行的分析結果這類信息彙總都是在END語句塊中完成,它 也是一個可選語句塊
   pattern語句塊中的通用命令是最重要的部分,也是可選的。如果 沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取 到的行,awk讀取的每一行都會執行該語句塊

三、AWK變量

  變量:內置變量和自定義變量

 1、內置變量

  FS:輸入字段分隔符,默認爲空白字符
   awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
   awk –F: '{print $1,$3,$7}’ /etc/passwd
  OFS:輸出字段分隔符,默認爲空白字符
   awk -v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd
   RS:輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效
   awk -v RS=' ' ‘{print }’ /etc/passwd
   ORS:輸出時的行分隔符,默認爲換行符
   awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
   NF:字段數量,當前行的字段數
   awk -F: ‘{print NF}’ /etc/fstab,顯示當前行的字段數
   awk -F: '{print $(NF-1)}' /etc/passwd 顯示當前行的第NF個字段
   NR:顯示行數;命令後跟的所有文件將統一合併計數
   awk '{print NR}' /etc/fstab
   awk END'{print NR}' /etc/fstab
   FNR:顯示行號;各文件分別計數,行號
   awk '{print FNR}' /etc/fstab /etc/inittab
  FILENAME:顯示當前文件名
   awk '{print FILENAME}’ /etc/fstab
   ARGC:命令行參數的個數
   awk '{print ARGC}’ /etc/fstab /etc/inittab
   awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
   ARGV:數組,保存的是命令行所給定的各參數
   awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
   awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
  注意:當引用這些內置變量時,不用加$;使用ARGC和ARGV時,後面可以是文件名,也可以是a b c d 任意值,不管是文件名或是任意字符串,以空格相隔,每一個值都會被賦值給ARGC這個數組的不同下標,默認從0開始,awk也是一個參數,awk是固定的被賦值給了ARGV[0],後面的所有參數按順序分配給各個下標,
  例:1.這個命令即是打印出這個參數的個數,加上awk本身總共5個
AWK的使用
    2.顯示各個參數的值
AWK的使用

 2、自定義變量

  自定義變量是區分字符大小寫的,自定義變量有兩種方法:

  1)-v var=value

  2)在program中直接定義

  例: awk -v test='hello gawk' '{print test}' /etc/fstab
    awk -v test='hello gawk' 'BEGIN{print test}'
    awk 'BEGIN{test="hello,gawk";print test}'
    awk –F:‘{sex=“male”;print $1,sex,age;age=18}’ /etc/passwd
  用-v選項和在program中定義的變量的區別,使用-v定義的變量,只有第一次執行的時候會讀取一次,在後面的program中弱勢變量值發生變化,便不可再回到初值,而program中的命令是每讀取一行的時候就會被執行一次,所以,當每讀取完一行的時候都會再次被賦值爲最初的那個值,所以可以根據自己的需求來選擇怎麼定義變量,在調用這些變量的值的時候不需要加$,所以如果要輸出一些字符串的時候,需要用上引號引起來,否則系統則會認爲是要調用變量名爲這串字符串的變量的值,

四、Print與printf

 1、print的格式

  print格式 print item1,item2...

  1)各intem之間逗號分隔符時,輸出各item以一個空格分隔

  2)輸出的各item可以是字符串,也可以是數值;當前記錄的字段、變量或awk的表達式

  3)如省略item,相當於print $0

  4)輸出空白字符:print “ “

   示例:

   awk '{print "hello world"}' 顯示字符串hello world
   awk -F: '{print}' /etc/passwd 顯示/etc/passwd文件中的所有內容
   awk -F: '{print "wang"}' /etc/passwd 每讀取/etc/passwd文件中一行內容輸出一次字符串“wang”
   awk -F: '{print $1}' /etc/passwd 每讀取一行,就截取以“:”爲分隔符的第一個字段
   awk -F: '{print $0}' /etc/passwd 顯示/etc/passwd文件中每一行以“:”分隔的所有字段(等同於awk -F: '{print}' /etc/passwd)
   awk -F: '{print$1"\t"$3}' /etc/passwd 輸出/etc/passwd每行第1和第3字段,中間以tab分隔
   tail -3 /etc/fatab |awk’{print $1,$4}’ 顯示/etc/fstab中最後3行的第1字段和第4字段

 2、printf格式化輸出

  printf “FORMAT” ,item1,item2...

   1)必須指定FORMAT(輸出格式符)

  2)不會自動換行,需要顯式給出換行控制符,\n,換行符必須放在FORMAT中才管用,跟在item後面是不對的

  3)FORMAT中需要爲後面每個item指定輸出格式符,否則item無法顯式,各item之間以逗號分隔

  輸出格式符(FORMAT):與item一一對應
   %c: 顯示字符的ASCII碼
   %d, %i: 顯示十進制整數
   %e, %E:顯示科學計數法數值
   %f:顯示爲浮點數
   %g, %G:以科學計數法或浮點形式顯示數值
   %s:顯示字符串
   %u:無符號整數
   %%: 顯示%自身
  修飾符:每一種格式符都有一些修飾符
   #[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後精度,%3.1f
   -: 左對齊(默認右對齊) %-15s
   +:顯示數值的正負符號 %+d
  示例:
   awk -F: ‘{printf "%s",$1}’ /etc/passwd
   awk -F: ‘{printf "%s\n",$1}’ /etc/passwd
   awk -F: ‘{printf "%-20s %10d\n",$1,$3}' /etc/passwd
   awk -F: ‘{printf "Username: %s\n",$1}’ /etc/passwd
   awk -F: ‘{printf “Username: %s,UID:%d\n",$1,$3}’ /etc/passwd
   awk -F: ‘{printf "Username: %15s,UID:%d\n",$1,$3}’ /etc/passwd
   awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’ /etc/passwd

五、AWK操作符

  算數操作符:
   x+y:加;
   x-y:減;
   x*y:乘;
   x/y:除;
   x^y:次方;
   x%y:取餘;x除以y得出的餘數
   -x:轉換爲負值,
   +x轉換爲數值
  字符串操作符:沒有符號的操作符,字符串連接
  賦值操作符:
   =:等於;
   +=:自加;例,x+=y,意思是把x本身的值加上y的值再賦給x
   -=: 自減;例,x-=y,意思是把x減去y的值再賦值給x
   *=: 自乘;例,x*=y,意思是把x乘以y的值再賦值給x
   /=: 自除;例,x/=y,意思是把x除以y的值再賦值給x
   %=:取餘賦值;例,x%=y,意思是x除以y後的餘數賦值給x
   ^=: 次方;例,x^=y,意思是把x的y次方的值再賦值給x
   ++:遞加;例,i++,意思是把i的值加1再賦值給i,等同於i+=1
   - -: 遞減;例,i- -,意思是把i的值減1再賦值給i,等同於i-=1
  比較操作符:
   = =: 等於
   !=: 不等於
   \>: 大於
   \>=: 大於等於
   <: 小於
   <= : 小於等於
  模式匹配符:
    ~:左邊是否匹配包含右邊
    !~: 是否左邊和右邊是否不匹配包含
  邏輯操作符:與&&;或||;非!
  示例:
   awk –F: '$0 ~ /root/{print $1}‘ /etc/passwd
   awk '$0~“^root"' /etc/passwd
   awk '$0 !~ /root/‘ /etc/passwd
   awk –F: ‘$3==0’ /etc/passwd
   awk –F: '$3\>=0 && $3\<=1000 {print $1}' /etc/passwd
   awk -F: '$3==0 || $3\>=1000 {print $1}' /etc/passwd
   awk -F: ‘!($3==0) {print $1}' /etc/passwd
   awk -F: ‘!($3\>=500) {print $3}’ /etc/passwd
  函數調用:function_name(argu1,argu2...)
  條件表達式(三目表達式):
   格式: selector?if-true-expression:if-false-expression
  三目表達式顧名思義就是有三個表達式組成的,問號之前的表達式通常爲判斷表達式,問號之後的表達式是滿足條件纔會執行的語句,冒號之後的是當不滿足條件時纔會執行的語句。
示例:
  awk -F: '{$3>=1000?usertype="common user":usertype="sysadmin or sysuser";printf "%15s: %-s\n" ,$1,usertype}' /etc/passwd

六、AWK條件判斷

  PATTERN:根據pattern條件,過濾匹配的行,再做處理

 1、如果爲指定:空模式,匹配每一行

 2、/regular expression/:僅處理能夠模式匹配到的行,需要用//括起來,//之間可以是字符串,也可以是正則表達式模糊匹配。

   awk '/^UUID/{print $1}' /etc/fstab
   awk '!/^UUID/{print $1}' /etc/fstab

 3、Relational expression:關係表達式,結果爲真纔會被處理

  真:結果爲非0值,非空字符串
  假:結果爲空字符串或0值
示例:
  awk -F: 'i=1;j=1{print i,j}' /etc/passwd
  awk ‘!0’ /etc/passwd
  awk ‘!1’ /etc/passwd
  awk –F: '$3\>=1000{print $1,$3}' /etc/passwd
  awk -F: '$3\<1000{print $1,$3}' /etc/passwd

  awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
  awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd

 4、Line ranges:行範圍

  Startline,endline:/pat1/,/pat2/不支持直接給出數字格式
  示例:
   awk -F: '/^\<root\>./,/^\<nobody\>./{print $0}' /etc/passwd
   awk -F: '/^\<root\>/,/^\<nobody\>/{print $0}' /etc/passwd
   awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd

 5、BEGIN/END模式

  BEGIN{}:僅在開始處理文件中的文本之前執行一次
  END{}:僅在文本處理完成之後執行一次

 6、示例:

  awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd
  awk -F : '{print "USER USERID“;print $1":"$3} END{print "end file"}' /etc/passwd
  awk -F: 'BEGIN{print " USER UID \n--------------- "}{print $1,$3}' /etc/passwd
  awk -F: 'BEGIN{print " USER UID \n--------------- "}{print $1,$3}'END{print "=============="} /etc/passwd
  seq 10 |awk ‘i=0’ 不顯示所有行
  seq 10 |awk ‘i=1’ 顯示所有行
  seq 10 | awk 'i=!i‘ 顯示基數行
  seq 10 |awk -v i=1 '!(i=!i)' 顯示基數行
  seq 10 | awk '{i=!i;print i}‘每執行一行,顯示一次i的真假值
  seq 10 | awk ‘!(i=!i)’ 顯示偶數行
  seq 10 |awk -v i=1 'i=!i' 顯示偶數行

七、AWK action

 1、常用的action分類

  1)expressions:算數,比較表達式

  2)Control statements:if,while等

  3)Compound statements:組合語句

  4)Input :輸入語句

  5)Output statements:輸出語句print等

 2、Awk控制語句if-else

  語法:if(condition){statement1}[else{statement2}]
     If(condition1){statement}else if(condition2){statement2}else{statement3}
  這種語法看着跟shell中的if--else語句相差無幾,第一種格式是單if語句,執行機制是先判斷條件(condition)部分,值爲則true執行statement1部分語句,值爲false則執行statement2部分的語句;第二種是多if語句,有多個條件多個語句,先判斷第一個條件(condition1),值爲true執行statement1部分的語句,值爲false就判斷下一個條件condition2,值爲true就執行statement2,值爲false就執行else後面的statement3語句;
  使用場景:對awk取得的整行或某個字段做條件判斷
   示例:
   awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
   awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
   awk '{if(NF\>5) print $0}' /etc/fstab
   awk -F: '{if($3\>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
   awk -F: '{if($3\>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd
   df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF\>=80{print $1,$5}‘
   awk 'BEGIN{ test=100;if(test\>90){print "very good"} else if(test\>60){ print "good"}else{print "no pass"}}'

 3、Awk循環語句while

  語法:while(condition){statement;...}
  執行機制:先判斷再執行,條件真,進入循環;條件假退出循環,statement部分可以有多個語句,組合語句,在statement處應該有一條是條件判斷的值發生變化的語句,否則容易進入死循環
  使用場景:對一行內的多個字段逐一類似處理時使用;對數組中的各元素逐一處理時使用
  示例:
   awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
   awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg

 4、Awk循環語句do-while

  語法:do{statement;}while(condition)
  執行機制:先執行再判斷,先執行一遍statement,再判斷condition,如果條件爲真則進入下一輪循環,如果爲假就退出,無論真假,至少執行一次循環體
  示例:
   awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}‘
思考:下面兩語句有何不同?
   awk ‘BEGIN{i=0;print ++i,i}’
   awk ‘BEGIN{i=0;print i++,i}’
AWK的使用
  前者輸出的++i是先給i加1在輸出,後者是先輸出i再給i加值

 5、Awk循環語句for

  語法:for (expr1;expr2;expr3){statement;...}
  常見用法:for(var assignment;condition;iteration process){for-body}
  執行機制:variable assignment(變量的初始值),condition(條件),iteration process(步長,也就是沒執行一次循環體後,使變量的值發生變化的語句);for-body(循環體),先賦初值變量(variable),再判斷變量的值是否符合條件(condition),符合就執行循環體部分(for-body),然後再給變量加上步長(iteration process),再判斷條件,爲真時執行循環體部分,爲假退出循環......
  特殊用法:for(var in array) {for-body}
  執行機制:給var多個值,一次使用一個值,執行一次循環,有多少個值就執行多少次循環,直到把array的所有的值都用完,array代表一個數組。
  示例:
   awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg

 6、性能比較

  性能比較就是,看某個命令從執行到出結果時的時長,哪個時間最短就說明哪個命令性能更好,這個查看性能的命令就是time,在命令的前面寫入time,把要執行的命令用小括號括起來,再執行此命令,就會在顯示執行結果的後面顯示出時間
  例:
  time(awk'BEGIN{ total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
  time(total=0;for i in {1..10000};do total=$(($total+i));done;echo $total)
  time(for ((i=0;i<=10000;i++));do let total+=i;done;echo $total)
  time(seq –s ”+” 10000|bc)

 7、Awk控制語句switch

  語法:switch(expression) {case VALUE1 or /REGEXP1/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
  執行機制:這個就相當於shell中的case語句,espression是一個表達式,當VALUE1的值滿足REGEXP1的時候執行statement1,當VALUE2的值滿足REGEXP2的時候,執行statement2語句,...當前面的所有條件都不滿足的時候,執行default後面的statement n語句。

 8、Awk控制語句break和continue

  這兩個語句的用法continue是提前結束當前這一輪循環,進入下一循環,break是結束當前的循環語句用於在for,while語句中
  示例:
   awk ‘BEGIN{sum=0;for(i=1;i<=100;i++) {if(i%2==0)continue;sum+=i}print sum}‘
   awk ‘BEGIN{sum=0;for(i=1;i<=100;i++) {if(i==66)break;sum+=i}print sum}

 9、Awk控制語句Next

  由於awk是逐行進行處理的,一行一行的處理,直到所有的行都被處理完結束,也相當於一個循環,next語句就相當於for、while循環語句的continue語句,用來結束對本行的處理而直接進入下一行處理。
  示例:
   awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

八、AWK數組

  關聯數組array[index-expression]
  Index-expression(下標):
   1)下標可以使用任意字符串;字符串要使用雙引號括起來,例:weekdays[“mon”]="Monday“
   2)如果某數組元素事先不存在,在引用時,awk會自動創建此元素,並將其值初始化爲“空串
   3)若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷
   4)若要遍歷數組中的每個元素,需使用for循環
   5)格式:for(var in array) {for-body} var會遍歷array的每個索引

  示例:
   awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"] ="Tuesday";for(i in weekdays) {print weekdays[i]}}‘
   netstat -tan | awk '/^tcp/{state[$NF]++}END {for(i in state) { print i,state[i]}}'
   awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
  例圖:
AWK的使用
  使用awk查看一個文件中的每一行的重複次數
AWK的使用

九、AWK函數

  函數分爲系統函數和自定義函數,

 1、系統函數

  數值處理:
   rand():返回0和1之間一個隨機數;使用這個函數之前必須先寫一個srand()語句,才能產生隨機0到1之間的小數,保留6位,如下圖:
AWK的使用
AWK的使用
  示例:產生10個0到100的隨機整數
AWK的使用
  字符串處理:
   length([s]):返回指定字符串的長度,並且在這種模式下,不管是字母數字還是漢字,都是一個佔用一個字符
AWK的使用
   sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並將第一個匹 配的內容替換爲s
AWK的使用
   gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並全部替換 爲s所表示的內容
AWK的使用
   split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存 至array所表示的數組中,第一個索引值爲1,第二個索引值爲2,…
  例圖:
AWK的使用

 2、自定義函數

  格式:
    function name ( parameter, parameter, ... ) {
     statements
     return expression
    }
  執行機制:把函數編輯在一個文件中,name是函數的名字,parameter是虛參,調用函數的括號內的實參,每一個實參對應着一個虛參,在函數中虛參是調用實參的值來執行statement部分的表達式,return的作用類似shell中的echo,是打印結果在終端上,expression可以是變量名或者是表達式,
  示例:編輯文件abc,寫一個函數,要求取最大值,
AWK的使用

十、調用系統命令

  格式:system(“cmd”)

 1、使用system時調用新系統命令的執行結果時,系統命令要用雙引號引起來,否則不會顯示任何結果,如下圖:

AWK的使用

 2、空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk的變量外其他一律用雙引號引起來。如下圖:

AWK的使用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章