AWK說明-及語法格式。

AWK簡介

  • awk是一款文本信息的統計,報告生成的工具.awk有自己的語法,是一款獨立的編程語言.
  • awk支持從文本文件中讀取內容,或者從標準的輸入中讀取內容.
  • awk 的最終起源於行編輯器ed,awk繼承了行編輯器的特點,循環的讀取文本的每一行(或者是分隔符分割的每一段文本)直至文本結束,但是awk加入了段分割符的概念.將每次讀入的行進行再次分割.awk每次讀取的行都只是未經過awk語句處理的對象。或讀取行後會根據段分割符在將行分成多個對象。結構近似數組,然後進行指定語句的操作
  • awk 的對命令的處理可以稱爲命令的解釋,或腳本語言的解釋。 awk的語句書寫格式,屬於模塊化風格,特別是if,else語句表現的特別明顯有點類似於bash中的匿名函數。每個語句塊必須使用{}進行約束

awk的基本執行過程:

  • 執行BEGIN語句塊中的內容,語句爲可選語句.多用於執行變量的初始化,報表的頭輸出.
  • 從標準輸入或文件中讀取行分割符(-F定義的字符)分割的行進入內存,進行語句之前的條件匹配,在沒有條件時默認爲符合執行條件.符合條件執行,不符合條件則嘗試匹配下一個語句之前的條件.直至所有條件匹配全部完成.當語句爲空時默認執行{print $0}
  • 繼續讀取下一行,直至末尾
  • 執行END定義的語句內容,同樣也爲可選語句.多用於報表的統計信息輸出.

基本格式 :

awk 選項 條件 語句 文件

  • 在bash命令行中執行awk時,在向awk傳入語句時,語句優先由bash優先解釋。也就是說可以向awk傳入語句時可以,bash展開傳入一些奇怪的東西,比如說系統變量,比如說{1..4}


  • 選項:

-f 從文件中讀取處理命令
-F 指明行的段分隔符;分割針對輸入時的數據。支持模式匹配。擴展的正則表達式,目的是將行分割成爲多個對象.或確定每次循環時待處理的對象(最小待處理單位)是什麼.默認的
-v 自定義變量
awk -v



  • 條件:

awk是一門語言,請以編程的視角去看待條件。
條件爲執行條件後的語句的要求。符合條件纔可執行語句,條件即爲對語句的判斷,可以使用正則匹配,基於正則的模式定界,字符串比較,可以使用算數條件表達式,也可以是BEGIN,END特殊條件。
算數條件表達式,最終返回運算結果,當運算結果爲0時,語句不執行。
在進行條件驗證時行已經被分割成最小的單位,並已經對最小單位的小數量,內容,行號等信息進行了統計。

  • 當條件爲空時執行每一行
例:正則_匹配正則匹配的每一行  
    awk '/^UUID/{print $1}' /etc/fstab   #匹配以UUID爲開始的行,並執行{}中的語句。print $1   
    awk '!/^UUID/{print $1}' /etc/fstab  #匹配以非UUID爲開始的行,執行{}中的語句 。print $1

例:算數計算_條件爲真該行纔會被處理 ,條件 爲假則不處理 。
    awp -F: '$3>=1000{print $1,$3}' /etc/passwd
    awp -F: '!$3>=1000{print $1,$3}' /etc/passwd
    awk -F: '(NR>=2&&NR<=10){print $1}'

例:字符串比較_比較結果爲真進入循環
    awk -F'$NF="/bin/bash"{print $1,$NF}' /bin/passwd
    awk -F'$NF~/bash$/{print $1,$NF}' /bin/passwd
    awk -F: '! ($NF=="/bin/bash")' /etc/passwd

例:行範圍_範圍內的行做處理 ,好像只支持模式定界
    awk -F'10,20{print $1}'  #----失敗了  
    awk -F'/^root/,/^myuser/{print $1}'

例:特殊條件_BEGIN/END 
    awk 'BEGIN{print "  username    ID  \n------------"}{printf "%10s:%-s" $1,$3}END{print "=========\n"}'
        # BEGIN:在開始之前顯示一次  
        # END:在文本處理完成 ,命令未完成時,執行一次

例:特殊條件_0,空
    awk -v aa="" 'aa' /etc/passwd     #變量aa的值爲空 ,(語句爲空執行默認語句)。但是條件爲空,不執行默認語句。
    awk -v aa=" " 'aa' /etc/passwd    #變量aa的值爲‘ ’空格不爲空執行默認語句
    awk -v aa="0" 'aa' /etc/passwd    #變量aa的值爲0,條件爲最終值爲0,默認語句不執行。
    awk -v aa="1" 'aa' /etc/passwd    #變量aa的值爲1 ,條件返回值爲1,默認語句執行。
    awk -v aa=0 'aa++' /etc/passwd    #aa初始值爲0,第一條語句條件爲a++,首先返回a的值在進行自加運算。所以打印第一行外所有行。
    echo "123"| awk -v a=1 'a=0{print $1}' #a的初始值爲1.第一條語句條件爲a=0,對a進行了重新賦值。此時返回a賦值後的值,條件爲0,語句不執行。


  • 語句:

符合條件執行的動作,awk是一門語言,所以以編程的思維去思考。只是awk的變量大多數是awk自動賦值的。並在內部根據自己的規則自動變化(比如行計數器NR,又比如$1等)
當{}中存在多條語句時使用;進行分隔。

 當語句爲空時,默認執行{print $0}
awk '!0' /etc/passwd

print :

打印 打印的類型需要進行設定 
“” 定義字符串 
數值直接爲數值
$爲最小元素引用
變量直接引用 
在不指定打印內容時,打印整個行(我就這麼一寫)
#在沒有指定條件,以及沒有指定print輸出的內容時,默認輸出整行
例:  >>echo "hello" |awk '{print}'
      hello

#在指定了多個輸出內容時,對象的格式不同,使用的定義也不同
例:     
    echo "hello word" |awk  '{print $1"\t"$2}'
    hello   word

    echo "hello word" |awk  -F' ' '{print $1"---"$2}'
    hello---word

    echo "hello word" |awk  -F' ' '{nu=10;print $1"---"$2"---"nu}'
    hello---word---10

#在沒有使用,分割字段時,默認字段是連續的,定義了輸出的字段,分割的是每個輸出的字段
例:
    echo "hello word" |awk  -F' ' '{print $1$2}'
    helloword

    echo "hello:word:haha:asd" |awk  -v FS=':' -v OFS='---' '{print $1$2}'
    helloword

    echo "hello:word:haha:asd" |awk  -v FS=':' -v OFS='---' '{print $1,$2}'
    hello---word

    echo "hello:word:haha:asd" |awk  -v FS=':' -v OFS='---' '{print $1,$2,$1$2}'
    hello---word---helloword

printf

格式化輸出字符串

格式符:
    %c ascii
        echo "asd"| awk '{printf "%c\n",$1}'

    %d i 十進制  整數  
        echo "123"| awk '{printf "%-d\n",$1}'

    %e %E 科學記數法 

    %f 顯示 浮點數  

    %s 顯示 字符串  
        echo "123"| awk '{printf "%s\n",$1}'
        123
        echo "123"| awk '{printf "%s\n","asd"}'
        asd

    %% 顯示%自身

    %g %G 以科學技術法顯示 

    %u 無符號的 整數 

修飾符 :
    # 顯示寬度  
    #。#;第二個  # 表示 小數點  後的精度 
    - : 左對齊,默認右對齊。
    + :顯示數字的正負符號

條件表達式:

格式:條件?條件爲真的語句:條件爲假的語句 
awk ‘{$3>=1000?usertype="......":usertype="::::::";printf "%15s:%-s\n",$1,usertype}’

控制語句:

if:
格式:
    if(條件){語句}
    if(條件){語句} else {語句}
例:
    awk -F: '{if($3>1000) print $1,$3}' /etc/passwd  #打印非系統用戶
    awk -F: '{if($3>1000){printf "普通用戶:%s",$1} else {printf "系統用戶:%s",$1}}' #對系統的用戶進行判斷,輸出結果。
    df -h |awk -F% '/\/dev\/sd/{print $1}'|awk '{if($NF>=16)print $1}'
    df -h |awk -F% '/\/dev\/sd/{print $1}'|awk '$NF>=16{print $1}'

循環語句:

whilewhile (條件) {語句}
        條件爲真進入循環 ,條件爲假退出循環。
    awk '/^[[:space:]]*linux/{i=1;while(i<NF){print $i,length($i);i++}}' /etc/grub2.cfg
    awk '/^[[:space:]]*linux/{i=1;while(i<NF){if(length($i)>7){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
dodo{語句} while(條件)
        首先執行do後面的語句。然後對while中的條件進行判斷。條件符合繼續執行do後的語句。
        awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}'
        awk 'BEGIN{total=0;i=0;while(i<=100){total+=i;i++};print total}'
forfor (i=1;i<10;i++){語句}
            awk /[[:space:]]*linux/{for(i=1;i<=NF;i++){print $i,length($i)}} /etc/grub2.cfg
        for可以實現遍歷數組元素 :
            格式 :for (i in 數組名稱)遍歷時 i被賦值的是每個索引,
switch
循環跳轉

break
        跳出當前循環,break # :跳出#層循環

contiune
        結束本次次循環, continue # :結束啊 #層的本次循環。

next :結束 當前行的處理,讀取下一行。gawk 的自帶循環 ,結束行的處理,進入下一行 
        awk -F: '{if($3%2!=0) next;print $0 }' /etc/passwd
        打印奇數行
delete
exit

函數:

內置函數

    lrngth
        統計指定字符串的長度,並返回。
        例:  echo "asdd"|awk '{print length($1)}' #統計字符串出現的次數。

randsrand
        rand,與srand 組合使用返回一個隨機數
        例: awk 'BEGIN{srand();for(i=1;i<=10;i++){print int(rand()*100)}}'

sub
        格式sub(r,s,[t])
        處理字符串t(可以是單純的字符串,變量,位置引用),對t進行模式匹配,模式定義在r中,將模式r所匹配的內容替換成s中的內容,但是隻進行1次替換
        例: echo "2008:08:08:08 08:08:08:08" |awk 'sub(/:/,"-",$0)'

gsub
        格式 gsub (r,s,[t])
        處理字符串t(可以是單純的字符串,變量,位置引用),對t進行模式匹配,模式定義在r中,將模式r所匹配的內容替換成s中的內容,對於待處理的字符串t進行全局替換。
        例: echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk '{gsub(/[^0-9]/,"",$0);print $0}'
        echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk 'gsub(/[^0-9]/,"",$0)'

split
        格式 split(a,array,[r])
        以r爲分隔符,分割字符串a,並將分割後的字符串分別存入數組,數組的下標從1開始,第一個索引爲1,第二個索引爲2.
        netstat -tan |awk '/^tcp/{split($4,ip,":");a[ip[1]]++}END{for(i in a){print i,a[ip[1]]}}'

int
        格式 int(需要轉換的小數,或字符串)
        將指定的內容轉換爲整數類型。

system
        格式: system("系統命令")
        將傳入的字符串以系統命令方式執行。命令先經過bash解釋傳入,所有傳入時到awk解釋時,必須保證是需求的字符,在經過awk解釋時,必須符合awk的語法。也就是保證經bash解釋後成爲符合awk語法格式切符合需求的字符。或者確保傳入的函數的值,爲需要的值。
        例:awk 'BEGIN{system("hostname")}'
           awk 'system("hostname"){i=0}'
自定義函數

    格式:
    function 函數名稱 (參數1 ,參數2 。。。){
    語句1 
    語句2
    return 數值
        }

將語句與函數定義在文件中,使用awk運行。
    #cat fun.awk
        function max(v1,v2) {
        v1>v2?var=v1:var=v2
        return var
        }
        BEGIN{a=3;b=2;print max(a,b)}
    #awk –f fun.awk

將語句與函數定義在腳本中,使用shebang,直接運行腳本。
將awk程序寫成腳本,直接調用或執行
    #cat f1.awk
        {if($3>=1000)print $1,$3}
    #awk -F: -f f1.awk /etc/passwd

    #cat f2.awk
        #!/bin/awk –f
        #this is a awk script
        {if($3>=1000)print $1,$3}
        #chmod +x f2.awk
    #f2.awk –F: /etc/passwd
awk腳本中傳遞參數:
格式:
awkfile var=value var2=value2... Inputfile
注意:在BEGIN過程中不可用。直到首行輸入完成以後,變
量纔可用。可以通過-v 參數,讓awk在執行BEGIN之前得到
變量的值。命令行中每一個指定的變量都需要一個-v參數
#cat test.awk
    #!/bin/awk –f
    {if($3 >=min && $3<=max)print $1,$3}
#chmod +x test.awk
#test.awk -F: min=100 max=200 /etc/passwd

數據引用:

行的分段引用
每個分段之間使用,進行分割,當不使用,進行分割時默認爲一個字段,
$1 :該行的第一個元素
$2 :該行的第一個元素
換行符有必要寫一下,換個行而已沒什麼神聖的,解釋了是換行不解釋就是\n,awk,看到的文本是連續的,或者說是一串,只是到了換行被截斷。

變量:

內建的變量。
    內建變量的賦值 -v FS=" " 每一個-v用來定義一個變量,
    FS:輸入的字段分割符,默認爲空白字符
    OFS:輸出的字段分隔符,默認也爲空白字符。
    RS:輸入時指明的行分割符,默認就是換行符,
    ORS:輸出時的行分隔符,默認爲換行符
    NF :行中的字段數量 
    NR :行計數器 ,如果跟了多個 文件  ,編號會連續 
    FNR : 基於文件的 行計數器 。
    FILENAME : 當前的文件名
    ARGC :命令行中的參數個數 
    ARGV :命令行中的參數 ,ARGV爲數組,參數爲命令自身及後跟隨的文件 ,語句不計入參數 
自定義的變量
    -v var=value
    在 與語句中 直接 定義  
    多條與語句之間 使用  ;分隔 

操作符

算數操作符 :
雙目運算符  :
x+y x-y x*y x/y x^y x%y
單目運算符 :
-x :將x 轉化爲負數 
+x :將字符串x 轉化爲 數值 
字符串的 操作符 :連接符什麼  鬼 
賦值操作符 :
+ += -= *= /= ^= %=
++  --
> >= < <= != ==

模式匹配:

~ : 是否匹配 
!~: 是否  不匹配  
邏輯操作符 :
 &&  || !
 函數調用 :
 函數名(參數 ,參數 )

數組:

awk的數組爲關聯數組,就是Python中的字典。
數組索引可以使用任意的字符串索引,字符串使用引號 
如果某數組元素不存在,引用時會創建初始值爲none,在進行數學運算時 none會自動轉化爲0進行計算。
數組賦值
array[\$1]=aa
array[\$1]++ 
awk '!arr[\$0]++' /etc/fstab
    排除重複的行,取出第一行是對應的數組的內容爲空,將none返回然後進行自加後值爲1,返回的值經過!取反爲真執行默認語句,同樣的語句第二次出現時,返回的值爲1,經過!取反,值爲假,反而不執行. 
awk '{arr[$0]++;print $0,arr[$0]}'
    打印並統計重複行出現的次數.

遍歷數組
netstat -tan | awk '/tcp\>/{stat{$NF}++}END{for(i in stat){print i,stat[i]}}

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