linux之Awk用法

參考地址:http://linux.chinaunix.net/techdoc/develop/2007/02/10/950229.shtml
html

http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html
linux

http://www.cnblogs.com/repository/archive/2011/05/13/2045927.html
shell

相較於 sed 經常做用於一整個行的處理, awk 則比較傾向於一行當中分紅數個『字段』來處理。 所以,awk 至關的適合處理小型的數據數據處理呢!awk 一般運做的模式是這樣的:
[root@linux ~]# awk '條件類型1{動做1} 條件類型2{動做2} ...' filename awk 能夠處理後續接的檔案,也能夠讀取來自前個指令的 standard output 。 但如前面說的, awk 主要是處理『每一行的字段內的數據』,而預設的『字段的分隔符爲 "空格鍵" 或 "[tab]鍵" 』!舉例來講,咱們用 last 能夠將登入者的數據取出來, 結果以下所示:
[root@linux ~]#lastdmtsai   pts/0        192.168.1.12     Mon Aug 22 09:40   still logged in
root     tty1                          Mon Aug 15 11:38 - 11:39  (00:01)
reboot   system boot  2.6.11           Sun Aug 14 18:18         (7+15:41)
dmtsai   pts/0        192.168.1.12     Fri Aug 12 12:07 - 12:08  (00:01)
若我想要取出帳號與登入者的 IP ,且帳號與 IP 之間以 [tab] 隔開,則會變成這樣:
[root@linux ~]# last | awk '{print $1 "\t" $3}'
dmtsai  192.168.1.12
root    Mon
reboot  boot
dmtsai  192.168.1.12
由於不論哪一行我都要處理,所以,就不須要有 "條件類型" 的限制!我所想要的是第一欄以及第三欄, 可是,第二行及第三行的內容怪怪的~這是由於數據格式的問題啊!因此囉~使用 awk 的時候,請先確認一下您的數據當中,若是是連續性的數據,請不要有空格或 [tab] 在內,不然,就會像這個例子這樣,會發生誤判喔!
另外,由上面這個例子您也會知道,在每一行的每一個字段都是有變量名稱的,那就是 $1, $2... 等變量名稱,以上面的例子來講, dmtsai 是 $1 ,由於他是第一欄嘛!至於 192.168.1.12 是第三欄, 因此他就是 $3 啦!後面以此類推~呵呵!還有個變數喔!那就是 $0 ,$0 表明『一整列資料』的意思~ 以上面的例子來講,第一行的 $0 表明的就是『dmtsai pts/0.... 』那一行啊! 由此可知,剛剛上面四行當中,整個 awk 的處理流程是:
bash

  • 讀入第一行,並將第一行的資料填入 $0, $1, $2.... 等變數當中;
    ide

  • 依據 "條件類型" 的限制,判斷是否須要進行後面的 "動做";
    ui

  • 作完全部的動做與條件類型;
    spa

  • 若還有後續的『行』的數據,則重複上面 1~3 的步驟,直到全部的數據都讀完爲止。通過這樣的步驟,您會曉得, awk 是『以行爲一次處理的單位』, 而『以字段爲最小的處理單位』。好了,那麼 awk 怎麼知道我到底這個數據有幾行?有幾欄呢?這就須要 awk 的內建變量的幫忙啦~
    變量名稱
    表明意義
    NF
    每一行 ($0) 擁有的字段總數
    NR
    目前 awk 所處理的是『第幾行』數據
    FS
    目前的分隔字符,預設是空格鍵
    咱們繼續以上面例子來作說明,若是我想要列出每一行的帳號,而且列出目前處理的行數, 而且說明,該行有多少字段,則能夠這樣 (注意, awk 後續的全部動做以 ' 括住, 因此,內容若是想要以 print 打印時,記得,非變量的文字部分,包含上一小節
    printf
    提到的格式中,都須要使用雙引號來定義出來喔!)
    [root@linux ~]# last | awk '{print $1 "\t lines: " NR "\t columes: " NF}'
    dmtsai   lines: 1        columes: 10
    root     lines: 2        columes: 9
    reboot   lines: 3        columes: 9
    dmtsai   lines: 4        columes: 10
    這樣能夠了解 NR 與 NF 的差異了吧?好了,底下來談一談所謂的 "條件類型" 了吧!
    penguin-s.gif
    awk 的邏輯運算字符

    既然有須要用到 "條件" 的類別,天然就須要一些邏輯運算囉~例如底下這些:
    運算單元
    表明意義
    >
    大於
    小於
    >=
    大於或等於
    小於或等於
    ==
    等於
    !=
    不等於
    值得注意的是那個 == 的符號,由於在『邏輯運算』上面, 就是所謂的大於、小於、等於等等的判斷式上面,咱們習慣上是以 == 來表示,而若是是直接給予一個值,例如變量設定時,就直接使用 = 而已。 好了,咱們實際來運用一下邏輯判斷吧!舉例來講,在 /etc/passwd 當中是以冒號 ":" 來做爲字段的分隔,那假設我要查閱,第三欄小於 10 如下的數據,而且僅列出帳號與第三欄, 那麼能夠這樣作:
    [root@linux ~]# cat /etc/passwd | \
    > awk '{FS=":"} $3
    root:x:0:0:root:/root:/bin/bash
    bin      1
    daemon   2
    ......(如下省略)......
    有趣吧!不過,怎麼第一行沒有正確的顯示出來呢?這是由於咱們讀入第一行的時候, 那些變數 $1, $2... 預設仍是以空格鍵爲分隔的,因此雖然咱們定義了 FS=":" 了, 可是卻僅能在第二行後纔開始生效。那麼怎麼辦呢?咱們能夠預先設定 awk 的變量啊! 利用 BEGIN 這個關鍵詞喔!這樣作:
    [root@linux ~]# cat /etc/passwd | \
    > awk 'BEGIN {FS=":"} $3 ......(如下省略)......
    頗有趣吧!而除了 BEGIN 以外,咱們還有 END 呢!另外,若是要用 awk 來進行『計算功能』呢?以底下的例子來看, 假設我有一個薪資數據表,內容是這樣的:
    Name    1st     2nd     3th
    VBird   23000   24000   25000
    DMTsai  21000   20000   23000
    Bird2   43000   42000   41000
    如何幫我計算每一個人的總額呢?並且我還想要格式化輸出喔! 你能夠將上面的數據儲存成一個名稱爲 pay.txt 的檔案,則:
    [root@linux ~]# cat pay.txt | \
    > awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" }
    NR>=2{total = $2 + $3 + $4
    printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
         Name        1st        2nd        3th      Total
        VBird      23000      24000      25000   72000.00
       DMTsai      21000      20000      23000   64000.00
        Bird2      43000      42000      41000  126000.00
    上面的例子有幾個重要事項應該要先說明的:
    .net


    • 全部的動做,亦即在 {} 內的動做,若是有須要多個指令輔助時,可利用分號『;』間隔, 或者直接以 [Enter] 按鍵來隔開每一個指令,例如上面的 NR>=2 後面接的動做, 利用 total = ... 那個指令來指定加總,然後續則以 printf 來格式化輸出!
      unix

    • 邏輯運算當中,若是是『等於』的狀況,則務必使用兩個等號『==』!
      htm

    • 格式化輸出時,在 printf 的格式設定當中,務必加上 \n ,才能進行分行!

    • 與 bash shell 的變量不一樣,在 awk 當中,變量能夠直接使用,不需加上 $ 符號。

    利用 awk 這個玩意兒,就能夠幫咱們處理不少平常工做了呢!真是好用的很~ 此外, awk 的輸出格式當中,經常會以
    printf 來輔助,因此, 最好您對 printf 也稍微熟悉一下比較好啦!另外, awk 的動做內 {} 也是支持 if (條件) 的喔! 舉例來講,上面的指令能夠修訂成爲這樣的[root@linux ~]# cat pay.txt | \> awk '{if(NR==1) printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}NR>=2{total = $2 + $3 + $4printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'你能夠仔細的比對一下上面兩個輸入有啥不一樣~從中去了解兩種語法吧! 我我的是比較傾向於使用第一種語法,由於會比較有統一性啊! ^_^
相關文章
相關標籤/搜索