awk 工具

  • awk 工具:相較於 sed 作用於一整個行的處理,awk 是『以行為一次處理的單位』, 而『以欄位為最小的處理單位』。
    1. awk 指令
      [root@linux ~]# awk '條件類型1{動作1} 條件類型2{動作2} ...' filename
      		
    2. 取出帳號與登入者的 IP:欄位的分隔符號為空白鍵或 [tab]
      [root@linux ~]# last
      csie   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)
      csie   pts/0        192.168.1.12     Fri Aug 12 12:07 - 12:08  (00:01)
      		
    3. 取出帳號與登入者的 IP,且帳號與 IP 之間以 [tab] 隔開:
      [root@linux ~]# last | awk '{print $1 "\t" $3}'
      csie  192.168.1.12
      root    Mon
      reboot  boot
      csie  192.168.1.12
      # 變數 $0 代表『一整列資料』,第一行的 $0 代表的就是『csie pts/0.... 』。
      		
  • awk 的內建變數
    1. 變數
      變數名稱 代表意義
      NF 每一行 ($0) 擁有的欄位總數
      NR 目前 awk 所處理的是『第幾行』資料
      FS 目前的分隔字元,預設是空白鍵
    2. 承上例:列出每一行的帳號,並列出目前處理的行數及該行有多少欄位。
      [root@linux ~]# last | awk '{print $1 "\t lines: " NR "\t columes: " NF}'
      csie     lines: 1        columes: 10
      root     lines: 2        columes: 9
      reboot   lines: 3        columes: 9
      csie     lines: 4        columes: 10
      		
  • awk 的邏輯運算
    1. 邏輯運算字元
      運算單元 代表意義
      > 大於
      < 小於
      >= 大於或等於
      <= 小於或等於
      == 等於
      != 不等於
    2. /etc/passwd 以冒號 ":" 作為欄位的分隔,查閱第三欄小於 10 以下的數據,並且僅列出帳號與第三欄:
      [root@linux ~]# cat /etc/passwd | \
      > awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
      root:x:0:0:root:/root:/bin/bash
      bin      1
      daemon   2
      ......(以下省略)......
      # 因讀入第一行時,變數 $1, $2... 預設還是以空白鍵為分隔。因此,第一行沒有正確的顯示。
      		
    3. 承上例,利用關鍵字 BEGIN 讓第一行正確顯示。
      [root@linux ~]# cat /etc/passwd | \
      > awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}'
      root     0
      bin      1
      daemon   2
      ......(以下省略)......
      		
    4. 計算每個人薪資總額並且格式化輸出,薪資資料表 pay.txt 如下:
      Name    1st     2nd     3th
      csie   23000   24000   25000
      Wang  21000   20000   23000
      Lin   43000   42000   41000
      [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
            csie      23000      24000      25000   72000.00
          Wang      21000      20000      23000   64000.00
           Lin      43000      42000      41000  126000.00
      # 在 {} 內的有多個指令時,可利用分號『;』,或 [Enter] 按鍵來隔開指令。
      # 與 bash shell 的變數不同,在 awk 當中,變數可以直接使用,不需加上 $ 符號。
      		
    5. 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 + $4
      printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
      		
    6. 例題:將如下 printf.txt 檔案內容以 awk 指令輸出,格式如下 printf.txt 輸出格式,其中每個欄位長度為 9 個字元。
      ## printf.txt 內容
      Name Chinese English Math
      Dmdyw 80 60 92
      csie 75 55 80
      Ken 60 90 70
      ##printf.txt輸出格式
           Name   Chinese   English      Math     Total
         Dmdyw        80        60        92    232.00
           csie        75        55        80    210.00
            Ken        60        90        70    220.00
      		
練習題
  1. 如何利用 awk 取出帳號與登入者的 IP,且帳號與 IP 之間以 [tab] 隔開?
    Sol. last | awk '{print $1 "\t" $3}'
  2. 如何利用 awk 取出帳號,並列出目前處理的行數及該行有多少欄位,且之間以預設的分隔字元隔開?
    Sol. last | awk '{print $1 FS NR FS NF}'
  3. /etc/passwd 以冒號 ":" 作為欄位的分隔,如何查閱第三欄小於等於 50 以下的數據,並且僅列出帳號與第三欄?
    Sol. cat /etc/passwd | awk 'BEGIN {FS=":"} $3 %*<== 50 {print $1 "\t " $3}'*)
  4. 如何輸出 /etc/man.config 至印表機?
    Sol. pr /etc/man.config 

文章來源:http://dywang.csie.cyut.edu.tw/dywang/linuxProgram...

arrow
arrow

    Johnson峰 發表在 痞客邦 留言(0) 人氣()