shell利器awk介紹與使用小案例

2020-08-14 19:09:34

強大的awk指令

1. awk簡介

awk 是一個強大的文字分析工具,它是 Linux 中功能強大的數據處理引擎之一,可能這麼說非常抽象,awk 可以非常輕鬆地處理比如每行都是相同格式的文字,比如日誌,cvs 格式等等。相對於 grep 的查詢,sed 的編輯,awk 在其對數據分析並生成報告時,顯得尤爲強大。本文,只是簡單介紹如何使用awk完成簡單的日常任務需求。

2. awk特性

  • 語句格式
    # 統配模式
    awk [options] 'script' file
    

    options 這個表示一些可選的參數選項,script 表示 awk 的可執行指令碼程式碼(一般被{} 花括號包圍),這個是必須的。file 這個表示 awk 需要處理的檔案,注意需要是純文字檔案(意味着 awk 能夠處理)。

    # 傳統模式
    awk [options] 'BEGIN{statement} {statement} END{statement}' file
    

    BEGIN: 在指令碼程式碼段前面使用 BEGIN 關鍵字時,它會在開始讀取一個檔案之前,執行一次 BEGIN 關鍵字後面的指令碼程式碼段, BEGIN 中的指令碼程式碼段只會執行一次,執行完之後 awk 程式就會退出。
    END: awk 的 END 指令和 BEGIN 恰好相反,在 awk 讀取並且處理完檔案的所有內容行之後,纔會執行 END 後面的指令碼程式碼段。

  • 內建變數
    awk中,常見和使用最爲頻繁的內建變數都在下面 下麪列舉了出來:
    1)NR: 表示檔案中的行號,表示當前是第幾行。
    2)NF: 表示檔案中的當前行被分割的列數,可以理解爲 MySQL 數據表裏面每一條記錄有多少個欄位,所以 NF就表示最後一個欄位,(NF-1) 就表示倒數第二個欄位。
    3)FS: 表示 awk 的輸入分隔符,預設分隔符爲空格和製表符,可以對其進行自定義設定。
    4)OFS: 表示 awk 的輸出分隔符,預設空格,也可以對其進行自定義設定。
    5)FILENAME: 表示當前檔案的檔名稱,如果同時處理多個檔案,它也表示當前檔名稱。
    6)RS: 行分隔符,用於分割行,預設換行符
    7)ORS: 輸出記錄的分隔符,預設換行符
    8)$符取值: $0 表示當前行中的數據。\$1,$2,$3...表示當前行中的第一列,第二列數據,第三列數據…
  • 內建函數
    awk 還提供了一些內建函數,在 awk 的 script 中編寫指令碼程式碼的時候,可以直接進行呼叫。比如:
    • toupper() 用於將字元轉爲大寫
    • tolower() 將字元轉爲小寫
    • length() 長度
    • substr() 子字串
    • sin() 正弦
    • cos() 餘弦
    • sqrt() 平方根
    • rand() 亂數
  • 運算子
    awk中的常見運算子有:

    賦值: =
    算術:+ - * / %
    比較:< <= == != > >= ~ !~~ 表示正則
    邏輯:&& || !

3. awk技巧

  • AWK使用的RE爲ERE
  • 如果在BEGIN中設定了OFS, 只有$0有改動OFS才能 纔能生效
  • printf與print的區別: printf不自動列印換行符, print則自動列印
  • gsub的返回值並不是替換後的字串,而是返回替換的次數
  • 字串常數一定在用」 「包圍起來,否則當作變數使用, 如$1==「ipaddress」
  • AWK 的 for 回圈爲C-Style,即爲for(),區別於shell中的for i in …
  • AWK中可以使用多個分隔符,要封裝在方括號裡,用’ ‘包圍,以防shell對它們進行解釋,如awk -F ‘[ :/t]’,使用空格,冒號,tab作爲分隔符
  • next語句:從輸入檔案中取得下一個輸入行,在AWK命令表頂部重新執行命令,一般用於跳過一些特殊的行
  • awk 匹配多個條件:awk ‘/kobe/ && /james/’,這會匹配同時有kobe和james的行
  • FS的預設值是[ /t/n]+, OFS的預設值爲空格,RS,ORS的預設值都是換行
  • exit語句:終止AWK程式,但不跳過END語句
  • {s1;s2;s3;…}中多個語句用分號隔開if; else if; else
  • print後不帶任何參數時,相當於print $0,將會列印整行記錄

運用awk

1. if,for語句

在使用 awk 讀取檔案或者檔案,或者文字的時候,我們需要在遍歷每一列,並將符合要求的列中的數據進行輸出。那麼我們就需要使用到 for 語句與 if 語句。具體語句用法同 shell 有區別。

  • for回圈寫法:
    #{}中用分號分隔多個動作
    for(i=1;i<=NF;i++){action1; action2; ..} 
    #for後接一個if結構
    for(i=1;i<=NF;i++) if; else if;else
    #簡單的回圈列印
    for(i=1;i<=NF;i++) printf "for add"
    
  • if判斷寫法:
    #else if部分可以沒有
    if($1 ~ /reg/){action1}; else if($1 ~ /reg2/){action2}; else{action3}
    #多個條件用」&&」,」||」表示
    if($1 ~ /reg/ && $2 ~ /reg2/){action}
    if($1 ~ /reg/ || NR >= 5){action}
    

2. 小案例

開始小案例的演示工作之前,我們需要準備份文字數據,方便指令要操作完成小案例。樣例數據(sample_data.txt):

this is sample data
i love shell program
2020 8 14 16 29
apple banana mango orange
so happy today

有了樣本數據,那麼我們就可以開始操作了,由於篇幅有限,只做個別演示。

  • 讀取文字中的每一行數據,並顯示行號。
    awk '{print NR "\t" $0}' sample_data.txt
    
    在这里插入图片描述
  • 輸出每一行中的第1,2,4列。
    awk '{print NR "\t" $1 " " $2 " "$4}' sample_data.txt
    
    在这里插入图片描述
  • 第3行,將它格式化爲日期,輸出形式:202-08-16。
    awk ' NR == 3 {$2='0'$2; print  $1 "-" $2 "-"$4}' sample_data.txt
    
    在这里插入图片描述
  • 嘗試處理文字,組合輸出:i love eat apple的文字。
    awk 'BEGIN{res="";} {if(NR == 2){res=$1" "$2;}else if(NR == 4){res=res" eat "$1;}} END{print res;}' sample_data.txt
    
    在这里插入图片描述
    有關 awk 的操作太多了,對於具體的需求,就需要具體使用了。關於 awk 的更多新技能,那就需要在使用的過程中慢慢探索咯。

編碼實踐是最有效,最高效的學習技能!
希望我們可以一起學習,一起編碼,一起成長進步!