Linux之awk

  

一:awk爲報告生成器


spacer.gif

wKioL1P7IkWyOEMRAABpBl-b3n0767.jpg

spacer.gif

AWK字段:awk對每行文檔按照分隔符(缺省爲空格指定的話爲-F)把行內的內容切成每個字段。

$0:代表整行。

$1...$N:代表被分割符分開的每個字段。


二:awk基本語法

基本語法: awk [options] 'program' file file ...

          awk [options] 'PATTERN{action}' file file ...


輸入選項 -F  指定分割符選項。

       

     
awk -F : '{print  $1 ,$7}'  /etc/passwd  #指定以冒號作爲字段分割符。默認是以空格



PATTERN: awk的輸出

                  print item1, item2, ........

 要點:
 (1) 各項目之間使用逗號分隔,而輸出時則使用輸出分隔符分隔;
 (2) 輸出的各item可以字符串或數值、當前記錄的字段、變量或awk的表達式;數值會被隱式轉換爲字符串後輸出;
 (3) print後面item如果省略,相當於print $0輸出整串內容;要想後面輸出空白,使用pirnt " " (在awk中輸出子串要使用雙引號);


遇到awk的錯誤需要注意的幾點

(1)確保整個a w k命令用單引號括起來。
(2)確保命令內所有引號成對出現。
(3)確保用花括號括起動作語句,用圓括號括起條件語句。
(4)可能忘記使用花括號,也許你認爲沒有必要,但a w k不這樣認爲,將按之解釋語法




awk的變量:內置變量,自定義變量

   內置變量:輸入時的字段分隔符 (awk的內置變量前要用BEGIN)

awk內置變量
A R G C 命令行參數個數
A R G V 命令行參數排列
E N V I R O N 支持隊列中系統環境變量的使用
FILENAME a w k瀏覽的文件名
F N R 瀏覽文件的記錄數
F S 設置輸入域分隔符,等價於命令行- F選項
N F 瀏覽記錄的域個數
N R 已讀的記錄數
O F S 輸出域分隔符
O R S 輸出記錄分隔符
R S 控制記錄分隔符
   FS:Field Seperator,  輸入時的字段分隔符相當於-F
#  awk 'BEGIN{FS=":"}{print $1,$7}' /etc/passwd  #內置變量的引用要用到雙引號



   OFS: Output Field Seperator, 輸出時的字段分隔符
#  awk 'BEGIN{FS=":";OFS=":"}{print $1,$7}' /etc/passwd     #語句與語句之間要用分號分割 (紅色部分)


   RS:Record Seperator, 輸入行分隔符
#  awk 'BEGIN{RS=":"}{print }' /etc/passwd   #會把冒號分開的內容當作每一行來處理

wKiom1P7If3iX_noAADtjNk1aK4594.jpg

   

  
ORS: Outpput Row Seperator, 輸出時的行分隔符在一行內容中
awk 'BEGIN{FS=":";ORS=":"}{print $1,$7}' /etc/passwd


         

wKiom1P7IlSQ-DYUAAGnaredKsU331.jpg

 

   

NF:Numbers of Field,字段數    #取最後一個字段還可用$NF
         
NR:Numbers of Record, 行數如果後面跟有多個文件的話那麼就是所有文件的一併計數;
# awk 'BEGIN{FS=":";OFS=":"}{print NR $1,$7}' /etc/passwd /etc/group


wKiom1P7I5PwimubAABqlRewKGw993.jpg

FNR:行數;各文件分別計數;
# awk 'BEGIN{FS=":";OFS=":"}{print FNR $1,$7}' /etc/passwd

wKioL1P7JQ-iVyqVAAECcpFX6Hs234.jpg

     

ARGV:數組,保存命令本身這個字符,awk '{print $0}' 1.txt 2.txt,意味着ARGV[0]保存awk,

  # awk 'BEGIN{print ARGV[0],ARGV[1],ARGV[2],ARGC}' /etc/passwd /etc/group

wKiom1P7JCSS0kiOAABo9Kv6z10251.jpg

  ARGC: 保存awk命令中參數的個數

  自定義變量:輸入時的字段分隔符 (awk的內置變量前要用BEGIN

  -v var_name=VALUE   變量名區分字符大小寫

  (1) 可以program中定義變量;

  (2) 可以命令行中通過-v選項自定義變量;


# awk 'BEGIN{a="hello awk"}{print a}' /etc/passwd


wKioL1P7JYyjQR0pAACatKHyeyc791.jpg


#awk 'BEGIN{a="hello awk";print a}'      #可以不跟文件  直接輸出hello awk
#awk -v a="hello awk" 'BEGIN{print a}'    #直接輸出hello awk

awk的printf命令


命令的使用格式:printf format, item1, item2,...  #print 後跟的直接打印內容要加上雙引號

要點:

  (1) 要指定format;

  (2) 不會自動換行;如需換行則需要給出\n

  (3) format用於爲後面的每個item指定其輸出格式;

  (4) 爲加入t a b鍵,使用t a b鍵速記引用符\ t


format格式的指示符都%開頭,後跟一個字符:

   %c: 顯示字符的ASCII碼;

   %d, %i: 十進制整數;

   %e, %E: 科學計數法顯示數值;

   %f: 顯示浮點數;

   %g, %G: 以科學計數法格式或浮點數格式顯示數值;

   %s: 顯示字符串

   %u: 顯示無符號整數;

   %%: 顯示%自身;

 修飾符:

   #:顯示寬度

   -:左對齊

   +:顯示數值的符號

   .#: 取值精度


# awk -F: '{printf "%15s %-15s\n",$1,$7}' /etc/passwd

wKioL1P7Jezx7DtvAAFFWrKT3JI478.jpg

 

   
# awk 'BEGIN {printf "%f\n",3.1415}'         #顯示7個字節


wKioL1P7JhnB-qtZAAA8c1BBAgg700.jpg


# awk 'BEGIN {printf "%f\n",3.1415926}'     #總位數超過8位,小數點後面要進行四捨五入


wKiom1P7JSvj4lC4AABBn1wV8T4765.jpg

   

# awk 'BEGIN {printf "%15.2f\n",3.1415926}'    #15.2 表示整體爲15個位寬加小數點後兩位


wKioL1P7JnXSLJPKAABFFslokO8387.jpg


# awk 'BEGIN {printf "name betle\n-----------"}{print $1"\t",$4}' /etc/passwd


awk輸出重定向

  print items > output-file

  print items >> output-file

  print items | command

  特殊文件描述符:

  /dev/stdin: 標準輸入

  /dev/stdout: 標準輸出

  /dev/stderr: 錯誤輸出

awk的操作符

          

算術操作符:
   x+y
   x-y
   x*y
   x/y
   x**y, x^y
   x%y
   -x:負值
   +x:轉換爲數值
  字符串操作符:連接
  賦值操作符:
   =
   +=
   -=
   *=
   /=
   %=
   ^=
   **=
   ++
   --
   如果模式自身是=號,要寫爲/=/
  比較操作符:
   <
   <=
   >
   >=
   ==
   !=
   ~:模式匹配,左邊的字符串能夠被右邊的模式所匹配爲真,否則爲假;
   !~:
邏輯操作符:
   &&: 與
   ||:或
  條件表達式:
  selector?if-true-expression:if-false-expression
  # awk -F: '{$3>=500?utype="common user":utype="admin or system user";print $1,"is",utype}' /etc/passwd
  函數調用:
  function_name(argu1,argu2)


                

正則表達式的使用

  模式匹配

   爲使一域號匹配正則表達式,使用符號‘~’後緊跟正則表達式,也可以用i f語句。a w k中i f後面的條件用()括起來。

cat test.txt

M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99   4712 Brown-2 12 30 28

awk '{if($4~/Brown/) print $0}' test.txt

 J.Troll 07/99 4842 Brown-3 12 26 26
 L.Tansl 05/99   4712 Brown-2 12 30 28
 
awk '$0 ~ /Brown/' test.txt   此方法也可以得到同樣的結果

 J.Troll 07/99 4842 Brown-3 12 26 26
 L.Tansl 05/99   4712 Brown-2 12 30 28

 精確匹配

  假定要使字符串精確匹配,比如說查看學生序號4 8,文件中有許多學生序號包含4 8,如果在f i e l d - 3中模式查詢序號4 8,a w k將返回所有序號帶4 8的記錄:

awk '{if($3~/48/) print $0}' test.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26

awk '{if ($3== "48") print $0}' test.txt  #準確匹配的內容要用雙引號 

P.Bunny 02/99 48 Yellow 12 35 28

awk '{if ($3="48" print $0)}' test.txt
M.Tans 5/99 48 Green 8 40 44
J.Lulu 06/99 48 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 48 Brown-3 12 26 26
L.Tansl 05/99 48 Brown-2 12 30 28

從上面的兩個例子可以看出 “=”和“==”是完全不同的一個是複製,一個是等於

不匹配

 假定$4不匹配Brown 都輸出

awk '$4 !~ /Brown/' test.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28


設置輸入域到域變量名

    在a w k中,設置有意義的域名是一種好習慣,在進行模式匹配或關係操作時更容易理解。一般的變量名設置方式爲n a m e = $ n,這裏n a m e爲調用的域變量名, n爲實際域號。例如設置學生域名爲n a m e,級別域名爲b e l t,操作爲n a m e = $ 1 ; b e l t s = $ 4。注意分號的使用,它分隔a w k命令。下面例子中,重新賦值學生名域爲n a m e,級別域爲b e l t s。查詢級別爲Ye l l o w的記錄,並最終打印名稱和級別。

awk '{name=$1;belts=$4;if(belts ~/Yellow/) print name" is belt "belts}' grade.txt

P.Bunny is belt Yellow


域值比較


有兩種方式測試一數值域是否小於另一數值域。

1) 在B E G I N中給變量名賦值。
2) 在關係操作中使用實際數值。
通常在B E G I N部分賦值是很有益的,可以在a w k表達式進行改動時減少很多麻煩。
使用關係操作必須用圓括號括起來。
下面的例子查詢所有比賽中得分在2 7點以下的學生。
用引號將數字引用起來是可選的,“2 7”、2 7產生同樣的結果。

awk 'BEGIN{BASELINE="27"} {if ($6<BASELINE) print $0}' grade.txt
J.Lulu 06/99 48317 green 9 24 26
J.Troll 07/99 4842 Brown-3 12 26 26


修改數值域或者取值

  當在a w k中修改任何域時,重要的一點是要記住實際輸入文件是不可修改的,修改的只是保存在緩存裏的a w k複本。a w k會在變量N R或N F變量中反映出修改痕跡。


  爲修改數值域,簡單的給域標識重賦新值,如: $ 1 = $ 1 + 5,會將域1數值加5,但要確保賦值域其子集爲數值型。


  修改M . Ta n s l e y的目前級別分域,使其數值從4 0減爲3 9,使用賦值語句$ 6 = $ 6 - 1,當然在實施修改前首先要匹配域名。

awk '{if($1=="M.Tans") {$6=$6-1};print $1,$6,$7}' grade.txt

M.Tans 39 44
J.Lulu 24 26
P.Bunny 35 28
J.Troll 26 26
L.Tansl 30 28
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章