標籤: 暫無標籤

1 Awk -awk釋義

  英文原義:Aho、Weinberger、Kernighan
  中文釋義:三位創造者Aho、Weinberger和Kernighan統稱

2 Awk -awk簡介

  AWK是一種優良的文本處理工具。它不僅是 Linux 中也是任何環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操作語言(其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母)的最大功能取決於一個人所擁有的知識。AWK 提供了極其強大的功能:可以進行樣式裝入、流控制、數學運算符、進程控制語句甚至於內置的變數和函數。它具備了一個完整的語言所應具有的幾乎所有精美特性。實際上 AWK 的確擁有自己的語言:AWK 程序設計語言, 三位創建者已將它正式定義為「樣式掃描和處理語言」。它允許您創建簡短的程序,這些程序讀取輸入文件、為數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。
  最簡單地說, AWK 是一種用於處理文本的編程語言工具。AWK 在很多方面類似於 shell 編程語言,儘管 AWK 具有完全屬於其本身的語法。它的設計思想來源於 SNOBOL4 、sed 、Marc Rochkind設計的有效性語言、語言工具 yacc 和 lex ,當然還從 C 語言中獲取了一些優秀的思想。在最初創造 AWK 時,其目的是用於文本處理,並且這種語言的基礎是,只要在輸入數據中有模式匹配,就執行一系列指令。該實用工具掃描文件中的每一行,查找與命令行中所給定內容相匹配的模式。如果發現匹配內容,則進行下一個編程步驟。如果找不到匹配內容,則繼續處理下一行。
  儘管操作可能會很複雜,但命令的語法始終是:
  awk '{pattern + action}' 或者 awk 'pattern {action}'
  其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令。花括弧 ({}) 不需要在程序中始終出現,但它們用於根據特定的模式對一系列指令進行分組。
  gawk 是 AWK 的 GNU 版本。
  一般的UNIX作業系統,本身即附有AWK,不同的UNIX作業系統所附的AWK其版本亦不盡相同,若讀者所使用的系統上未附有AWK,可通過 anonymous ftp 到下列地方取得:
  phi.sinica.edu.tw:/pub/gnu
  ftp.edu.tw:/UNIX/gnu
  prep.ai.mit.edu:/pub/gnu
  注 解:一種編程語言,因其模式匹配語法而特別有用,通常用於數據檢索和數據轉換。一個GNU版本稱為Gawk。

3 Awk -調用方式

  awk提供了適應多種需要的不同解決方案,它們是:
  一、 awk命令行,你可以象使用普通UNIX命令一樣使用awk,在命令行中你也可以使用awk程序設計語言,雖然awk支持多行的錄入,但是錄入長長的命令行並保證其正確無誤卻是一件令人頭疼的事,因此,這種方法一般只用於解決簡單的問題。當然,你也可以在shell script程序中引用awk命令行甚至awk程序腳本。
  二、使用-f選項調用awk程序。awk允許將一段awk程序寫入一個文本文件,然後在awk命令行中用-f選項調用並執行這段程序。具體的方法我們將在後面的awk語法中講到。
  三、利用命令解釋器調用awk程序:利用UNIX支持的命令解釋器功能,我們可以將一段awk程序寫入文本文件,然後在它的第一行加上:
  #!/bin/awk -f
  並賦予這個文本文件以執行的許可權。這樣做之後,你就可以在命令行中用類似於下面這樣的方式調用並執行這段awk程序了。
  awk腳本文本名 待處理文件

4 Awk -語法

  與其它UNIX命令一樣,awk擁有自己的語法:
  awk [ -F re] [parameter...] ['prog'] [-f progfile]
  參數說明:
  -F re:允許awk更改其欄位分隔符。
  parameter: 該參數幫助為不同的變數賦值。
  'prog': awk的程序語句段。這個語句段必須用單拓號:'和'括起,以防被shell解釋。這個程序語句段的標準形式為:
  'pattern {action}'
  其中pattern參數可以是egrep正則表達式中的任何一個,它可以使用語法/re/再加上一些樣式匹配技巧構成。與sed類似,你也可以使用"," 分開兩樣式以選擇某個範圍。關於匹配的細節,你可以參考附錄,如果仍不懂的話,找本UNIX書學學grep和sed(本人是在學習ed時掌握匹配技術的)。action參數總是被大括弧包圍,它由一系列awk語句組成,各語句之間用";"分隔。awk解釋它們,並在pattern給定的樣式匹配的記錄上執行其操作。與shell類似,你也可以使用「#」作為註釋符,它使「#」到行尾的內容成為註釋,在解釋執行時,它們將被忽略。你可以省略pattern和 action之一,但不能兩者同時省略,當省略pattern時沒有樣式匹配,表示對所有行(記錄)均執行操作,省略action時執行預設的操作——在標準輸出上顯示。
  -f progfile:允許awk調用並執行progfile指定有程序文件。progfile是一個文本文件,他必須符合awk的語法。
  in_file:awk的輸入文件,awk允許對多個輸入文件進行處理。值得注意的是awk不修改輸入文件。如果未指定輸入文件,awk將接受標準輸入,並將結果顯示在標準輸出上。awk支持輸入輸出重定向。

5 Awk -記錄、欄位與內置變數

  前面說過,awk處理的工作與資料庫的處理方式有相同之處,其相同處之一就是awk支持對記錄和欄位的處理,其中對欄位的處理是grep和sed不能實現的,這也是awk優於二者的原因之一。在awk中,預設的情況下總是將文本文件中的一行視為一個記錄,而將一行中的某一部分作為記錄中的一個欄位。為了操作這些不同的欄位,awk借用shell的方法,用1,2,3...這樣的方式來順序地表示行(記錄)中的不同欄位。特殊地,awk用0表示整個行(記錄)。不同的欄位之間是用稱作分隔符的字元分隔開的。系統默認的分隔符是空格。awk允許在命令行中用-F re的形式來改變這個分隔符。事實上,awk用一個內置的變數FS來記憶這個分隔符。awk中有好幾個這樣的內置變數,例如,記錄分隔符變數RS、當前工作的記錄數NR等等,本文後面的附表列出了全部的內置變數。這些內置的變數可以在awk程序中引用或修改,例如,你可以利用NR變數在模式匹配中指定工作範圍,也可以通過修改記錄分隔符RS讓一個特殊字元而不是換行符作為記錄的分隔符。
  例:顯示文本文件myfile中第七行到第十五行中以字元%分隔的第一欄位,第三欄位和第七欄位:
  awk -F % 'NR==7,NR==15 {print $1 $3 $7}' myfile

6 Awk -內置函數

  awk 之所以成為一種優秀的程序設計語言的原因之一是它吸收了某些優秀的程序設計語言(例如C)語言的許多優點。這些優點之一就是內置函數的使用,awk定義並支持了一系列的內置函數,由於這些函數的使用,使得awk提供的功能更為完善和強大,例如,awk使用了一系列的字元串處理內置函數(這些函數看起來與C 語言的字元串處理函數相似,其使用方式與C語言中的函數也相差無幾),正是由於這些內置函數的使用,使awk處理字元串的功能更加強大。本文後面的附錄中列有一般的awk所提供的內置函數,這些內置函數也許與你的awk版本有些出入,因此,在使用之前,最好參考一下你的系統中的聯機幫助。
  內置的字元串函數
  
gsub(r,s)在整個$0中用s代替r
gsub(r,s,t)在整個t中用s替代r
index(s,t)返回s中字元串t的第一位置
length(s)返回s長度
match(s,r)測試s是否包含匹配r的字元串
split(s,a,fs)在fs上將s分成序列a
sprint(fmt,exp)返回經fmt格式化后的exp
sub(r,s)用$0中最左邊最長的子串代替s
substr(s,p)返回字元串s中從p開始的後綴部分
substr(s,p,n)返回字元串s中從p開始長度為n的後綴部分
 gsub函數有點類似於sed查找和替換。它允許替換一個字元串或字元為另一個字元串或字元,並以正則表達式的形式執行。第一個函數作用於記錄$0,第二個gsub函數允許指定目標,然而,如果未指定目標,預設為$0。
  index(s,t)函數返回目標字元串s中查詢字元串t的首位置。length函數返回字元串s字元長度。
  match函數測試字元串s是否包含一個正則表達式r定義的匹配。
  split使用域分隔符fs將字元串s劃分為指定序列a。
  sprint函數類似於printf函數,返回基本輸出格式fmt的結果字元串exp。
  sub(r,s)函數將用s替代$0中最左邊最長的子串,該子串被r匹配。
  sub(s,p)返回字元串s在位置p后的後綴。
  substr(s,p,n)同上,並指定子串長度為n。

7 Awk -命令行使用

  按照順序,我們應當講解awk程序設計的內容了,但在講解之前,我們將用一些例子來對前面的知識進行回顧,這些例子都是在命令行中使用的,由此我們可以知道在命令行中使用awk是多麼的方便。這樣做的原因一方面是為下面的內容作鋪墊,另一方面是介紹一些解決簡單問題的方法,我們完全沒有必要用複雜的方法來解決簡單的問題----既然awk提供了較為簡單的方法的話。
  例:顯示文本文件mydoc匹配(含有)字元串"sun"的所有行。
  awk '/sun/' mydoc
  由於顯示整個記錄(全行)是awk的預設動作,因此可以省略action項。
  awk '/sun/' mydoc
  例:下面是一個較為複雜的匹配的示例:
  awk '/[Ss]un/,/[Mm]oon/ ' myfile
  它將顯示第一個匹配Sun或sun的行與第一個匹配Moon或moon的行之間的行,並顯示到標準輸出上。
  例:下面的示例顯示了內置變數和內置函數length()的使用:
  awk 'length($0)>80 {print NR}' myfile
  該命令行將顯示文本myfile中所有超過80個字元的行號,在這裡,用0表示整個記錄(行),同時,內置變數NR不使用標誌符''。
  例:作為一個較為實際的例子,我們假設要對UNIX中的用戶進行安全性檢查,方法是考察/etc下的passwd文件,檢查其中的passwd欄位(第二欄位)是否為"*",如不為"*",則表示該用戶沒有設置密碼,顯示出這些用戶名(第一欄位)。我們可以用如下語句實現:
  #awk -F: '$2!="*" {printf("%s no password!\n",$1)'} /etc/passwd
  在這個示例中,passwd文件的欄位分隔符是「:」,因此,必須用-F:來更改默認的欄位分隔符,這個示例中也涉及到了內置函數printf的使用。

8 Awk -awk內置變數詳細介紹

  awk提供了有很多內置變數,如果你經常使用awk處理文本,了解這些這些內置變數的使用是很有必要的。下面看一下這些內置變數的詳細介紹。
  ARGC 命令行參數個數(不包括awk的選項和awk的程序內容)。
  ARGIND 當前正在處理的ARGV中的文件的索引值(同時處理多個文件時會用到)。
  ARGV 命令行參數序列數組,下標從0開始。
  CONVFMT 數字轉換格式,和C語言中的數字輸出格式化類似,默認為"%.6g"。
  ENVIRON 當前系統的環境變數。
  ERRNO 出錯時的錯誤信息。
  FIELDWIDTHS 以空格分隔的欄位寬度,如果指定此變數,awk將會用指定的寬度替換變數FS指定的分隔符。看下面的例子:
  [LinuxSong@test /tmp]$ cat t
  abcdefasfa
  abcdefasfa
  abcdefasfa
  [LinuxSong@test /tmp]$ awk 'BEGIN {FIELDWIDTHS="2 3 4"}{print $1,$2,$3}' t
  ab cde fasf
  ab cde fasf
  ab cde fasf
  FILENAME 當前正在處理的文件名,該變數不能在BEGIN塊中使用。
  FNR 當前處理的記錄號。
  FS 欄位的分隔符,默認為空格。
  IGNORECASE 如果該變數設置為非0值,在進行字元串匹配時忽略大小寫。
  NF 當前記錄中的欄位個數。
  NR 已經讀出的記錄數。
  OFMT 數字的輸出格式。
  OFS 輸出的欄位分隔符,默認為空格。
  ORS 輸出的記錄分隔符,默認為新行。
  RS 輸入記錄的分隔符,默認為新行。
  RSTART 被match()函數匹配的字元串的起始位置,如果沒有匹配則為0(從1開始)。
  RLENGTH 被match()函數匹配的字元串的長度。
  SUBSEP 數組中多個下標的分隔符,默認為"\034"。

9 Awk -變數

  如同其它程序設計語言一樣,awk允許在程序語言中設置變數,事實上,提供變數的功能是程序設計語言的基本要求,不提供變數的程序設計語言本人還從未見過。
  awk 提供兩種變數,一種是awk內置的變數,這前面我們已經講過,需要著重指出的是,與後面提到的其它變數不同的是,在awk程序中引用內置變數不需要使用標誌符""(回憶一下前面講過的NR的使用)。awk提供的另一種變數是自定義變數。awk允許用戶在awk程序語句中定義並調用自已的變數。當然這種變數不能與內置變數及其它awk保留字相同,在awk中引用自定義變數必須在它前面加上標誌符""。與C語言不同的是,awk中不需要對變數進行初始化, awk根據其在awk中第一次出現的形式和上下文確定其具體的數據類型。當變數類型不確定時,awk默認其為字元串類型。這裡有一個技巧:如果你要讓你的 awk程序知道你所使用的變數的明確類型,你應當在在程序中給它賦初值。在後面的實例中,我們將用到這一技巧。

10 Awk -運算與判斷

  作為一種程序設計語言所應具有的特點之一,awk支持多種運算,這些運算與C語言提供的基本相同:如+、-、*、/、%等等,同時,awk也支持C語言中類似++、--、+=、-=、=+、=-之類的功能,這給熟悉C語言的使用者編寫awk程序帶來了極大的方便。作為對運算功能的一種擴展,awk還提供了一系列內置的運算函數(如log、sqr、cos、sin等等)和一些用於對字元串進行操作(運算)的函數(如length、substr等等)。這些函數的引用大大的提高了awk的運算功能。
  作為對條件轉移指令的一部分,關係判斷是每種程序設計語言都具備的功能,awk也不例外。awk 中允許進行多種測試,如常用的==(等於)、!=(不等於)、>;(大於)、=(大於等於)、>=(小於等於)等等,同時,作為樣式匹配,還提供了~(匹配於)和!~(不匹配於)判斷。
  作為對測試的一種擴充,awk也支持用邏輯運算符:!(非)、&&;(與)、||(或)和括弧()進行多重判斷,這大大增強了awk的功能。本文的附錄中列出了awk所允許的運算、判斷以及操作符的優先順序。

11 Awk -流程式控制制

  流程式控制制語句是任何程序設計語言都不能缺少的部分。任何好的語言都有一些執行流程式控制制的語句。awk提供的完備的流程控制語句類似於C語言,這給我們編程帶來了極大的方便。1、BEGIN和END

  在awk 中兩個特別的表達式,BEGIN和END,這兩者都可用於pattern中(參考前面的awk語法),提供BEGIN和END的作用是給程序賦予初始狀態和在程序結束之後執行一些掃尾的工作。任何在BEGIN之後列出的操作(在{}內)將在awk開始掃描輸入之前執行,而END之後列出的操作將在掃描完全部的輸入之後執行。因此,通常使用BEGIN來顯示變數和預置(初始化)變數,使用END來輸出最終結果。
  例:累計銷售文件xs中的銷售金額(假設銷售金額在記錄的第三欄位):
  awk
  >'BEGIN { FS=":";print "統計銷售金額";total=0}
  >{print 3;total=total+3;}
  >END {printf "銷售金額總計:%.2f",total}' sx
  (註:>;是shell提供的第二提示符,如要在shell程序awk語句和awk語言中換行,則需在行尾加反斜杠\)
  在這裡,BEGIN預置了內部變數FS(欄位分隔符)和自定義變數total,同時在掃描之前顯示出輸出行頭。而END則在掃描完成後列印出總合計。2、流程式控制制語句

  awk提供了完備的流程式控制制語句,其用法與C語言類似。下面我們一一加以說明:
  2.1、if...else語句:
  格式:
  if(表達式)
  語句1
  else
  語句2
  格式中"語句1"可以是多個語句,如果你為了方便awk判斷也方便你自已閱讀,你最好將多個語句用{}括起來。awk分枝結構允許嵌套,其格式為:
  if(表達式1)
  {if(表達式2)
  語句1
  else
  語句2
  }
  語句3
  else {if(表達式3)
  語句4
  else
  語句5
  }
  語句6
  當然實際操作過程中你可能不會用到如此複雜的分枝結構,這裡只是為了給出其樣式罷了。
  2.2、while語句
  格式為:
  while(表達式)
  語句
  2.3、do-while語句
  格式為:
  do
  {
  語句
  }while(條件判斷語句)
  2.4、for語句
  格式為:
  for(初始表達式;終止條件;步長表達式)
  {語句}
  在awk 的 while、do-while和for語句中允許使用break,continue語句來控制流程走向,也允許使用exit這樣的語句來退出。break 中斷當前正在執行的循環並跳到循環外執行下一條語句。continue從當前位置跳到循環開始處執行。對於exit的執行有兩種情況:當exit語句不在 END中時,任何操作中的exit命令表現得如同到了文件尾,所有模式或操作執行將停止,END模式中的操作被執行。而出現在END中的exit將導致程序終止。

12 Awk -Awk中的自定義函數

  定義和調用用戶自己的函數是幾乎每個高級語言都具有的功能,awk也不例外,但原始的awk並不提供函數功能,只有在nawk或較新的awk版本中才可以增加函數。
  函數的使用包含兩部分:函數的定義與函數調用。其中函數定義又包括要執行的代碼(函數本身)和從主程序代碼傳遞到該函數的臨時調用。
  awk函數的定義方法如下:
  function 函數名(參數表){
  函數體
  }
  在gawk中允許將function省略為func,但其它版本的awk不允許。函數名必須是一個合法的標誌符,參數表中可以不提供參數(但在調用函數時函數名后的一對括弧仍然是不可缺少的),也可以提供一個或多個參數。與C語言相似,awk的參數也是通過值來傳遞的。
  在awk 中調用函數比較簡單,其方法與C語言相似,但awk比C語言更為靈活,它不執行參數有效性檢查。換句話說,在你調用函數時,可以列出比函數預計(函數定義中規定)的多或少的參數,多餘的參數會被awk所忽略,而不足的參數,awk將它們置為預設值0或空字元串,具體置為何值,將取決於參數的使用方式。
  awk函數有兩種返回方式:隱式返回和顯式返回。當awk執行到函數的結尾時,它自動地返回到調用程序,這是函數是隱式返回的。如果需要在結束之前退出函數,可以明確地使用返回語句提前退出。方法是在函數中使用形如:return 返回值 格式的語句。
  例:下面的例子演示了函數的使用。在這個示例中,定義了一個名為print_header的函數,該函數調用了兩個參數FileName和 PageNum, FileName參數傳給函數當前使用的文件名,PageNum參數是當前頁的頁號。這個函數的功能是列印(顯示)出當前文件的文件名,和當前頁的頁號。完成這個功能后,這個函數將返回下一頁的頁號。
  nawk
  >'BEGIN{pageno=1;file=FILENAME
  >pageno=print_header(file,pageno);#調用函數print_header
  >printf("當前頁頁號是:%d\n",pageno);
  >}
  >#定義函數print_header
  >function print_header(FileName,PageNum){
  >printf("%s %d\n",FileName,PageNum); >PageNum++;return PageNUm;
  >}
  >}' myfile
  執行這個程序將顯示如下內容:
  myfile 1
  當前頁頁號是:2

13 Awk -高級輸入輸出

  1.讀取下一條記錄:
  awk的next語句導致awk讀取下一個記錄並完成模式匹配,然後立即執行相應的操作。通常它用匹配的模式執行操作中的代碼。next導致這個記錄的任何額外匹配模式被忽略。
  2.簡單地讀取一條記錄
  awk 的 getline語句用於簡單地讀取一條記錄。如果用戶有一個數據記錄類似兩個物理記錄,那麼getline將尤其有用。它完成一般欄位的分離(設置欄位變數0 FNR NF NR)。如果成功則返回1,失敗則返回0(到達文件尾)。如果需簡單地讀取一個文件,則可以編寫以下代碼:
  例:示例getline的使用
  {while(getline==1)
  {
  #process the inputted fields
  }
  }
  也可以使getline保存輸入數據在一個欄位中,而不是通過使用getline variable的形式處理一般欄位。當使用這種方式時,NF被置成0,FNR和NR被增值。
  用戶也可以使用getline"datafile"
  或
  printf("hello word!\n"
  >>"datafile"
  3. 輸出記錄
  可以通過print 和 printf 將結果輸出:
  awk '{ print $1,$2 }' file
  4.輸出到一個命令
  awk中允許用如下方式將結果輸出到一個命令:
  printf("hello word!\n"
  |"sort-t','"
  awk與shell script混合編程
  因為awk可以作為一個shell命令使用,因此awk能與shell批處理程序很好的融合在一起,這給實現awk與shell程序的混合編程提供了可能。實現混合編程的關鍵是awk與shell script之間的對話,換言之,就是awk與shell script之間的信息交流:awk從shell script中獲取所需的信息(通常是變數的值)、在awk中執行shell命令行、shell script將命令執行的結果送給awk處理以及shell scri
上一篇[弗蘭斯蒂德星表]    下一篇 [八角金盆]

相關評論

同義詞:暫無同義詞