揭開sed和awk的祕密

如果你經常使用正則表達式(regular expression),那麼一定熟悉UNIX的兩個文本工具:sed和awk。

      這兩個工具很易學,而且都對模式匹配(patten match*譯者注:這裏的意思應該是給定若干的條件,對符合條件的對象進行預定的處理,也可以說是條件匹配*)很有用。Sed是流編輯器;它由命令 simple ed得名;awk是一種編程語言,它的名字是它的三個開發者名字(Aho、Weinberger和Kernighan)的首字母組合得到的。我將在本文中 介紹sed和awk的基本知識,進一步的知識將在以後的幾篇文章中闡述。


       Sed和awk都很勝任自動單調的(automating monotonous)文本編輯任務,該任務一般在文本編輯器用交互方式完成的。Sed和awk都是基於流的,也就是說它們的輸入來自文本文件中——一次得到一行——然後產生標準輸出。

      Sed 主要用於對單個或多個文件的重複編輯。Awk,做爲一種編程語言,可以用來處理結構化的數據,然後產生格式化的報告。Sed和awk都可以像外殼腳本 (shell script)那樣被執行;每一個動作都是順序運行的。Sed腳本通常用於簡單任務,如完成條目(如從一個或者一系列文件中獲取的方法的名字)的連接。 Awk更適合完成複雜的任務,如重新格式化數據或建立定製報告(custom report)。

        Awk是一個完整的編程語言,它的作用不限於sed那樣的文本編輯器。Awk擅長從系統記錄(system log)或來自數據庫(該數據庫基於文本)的數據來生成報告。然而,爲了發揮awk的用處,數據必須是結構化的,這是awk本身所決定的。

表A

sed

awk

  • Double/triple-space a file
  • 轉化DOS/UNIX 的新行(newline)
  • 刪除前後的空格
  • 在所有/全部行上進行取代操作
  • 刪除連續的空行
  • 刪除文件開頭和結尾的空行
  • 管理小的、個人的數據庫
  • 產生報告
  • 驗證數據
  • 生成下標、執行其它文檔預備任務
  • 試驗算法,這些算法稍後可以由其它語言實現
  • 處理UNIX命令的結果
  • 更合理地處理命令行的參數

 

Sed和awk的常見用法

       Sed與awk使用類似的語法,這就簡化了對它們的學習過程。Sed程序由命令行組成,而awk程序是由編程語句和函數組成的。


Sed的運行過程


       我們已經提到,sed腳本是順序執行的。首先,模式匹配上了,程序就開始運行。然後,對輸入文件的當前行運行腳本文件,每運行腳本文件的一行,都產生相應的輸出。但腳本中的所有命令行都執行完了之後,sed開始對對輸入文件的下一行開始執行腳本中的指令。

你可以在UNIX的命令行中這樣調用sed:
#sed [選項] 腳本文件/命令輸入文件

       下面以一個記載聯繫方式的名爲phonelist.txt文件爲例,介紹sed的用法。記錄中包括姓名、家庭電話、宿舍電話和E-mail地址:
John Doe, 100-555-1111, 100-555-1112,
Jane Doe, 100-555-2222, 100-555-1113,
Jimmy Dean, 101-555-1111, 101-555-2222,

讓我們首先看看比較簡單的sed編輯命令:

$sed ‘s/100-/(100) /’ phonelist.txt

該命令將把區號爲100的第一個電話號碼從xxx-xxx-xxxx格式轉換到(xxx) xxx-xxxx格式。

如果我們想對所有的區號爲100的電話號碼都做上述格式轉換,就需要使用/g選項。
$sed ‘s/100-/(100) /g’ phonelist.txt

該操作作用於輸入文件的所有的行。我們也可以在一個命令行上執行多個指令,這可以通過使用-e選項,也可以用分號(;)來分隔命令,如:
$sed –e ‘s/100-/(100) /g’-e ‘s/101-/(101) /g’ phonelist
$sed ‘s/100-/(100) /g’; ‘s/101-/(101) /g’ phonelist
(* 譯者注:注意要把輸入文件的行和命令行區分開來,前者在本例中指得是文件phonelist.txt的某一行,如“John Doe, 100-555-1111, 100-555-1112, ”,後者指的是sed用戶在敲入UNIX的命令行或者sed腳本文件中的某一行。*)

當需要使用多個命令時,用腳本文件也許更加合適。腳本文件的格式很簡單——一行寫一條命令:
$sed –f scriptfile inputfile

我們可以用外殼重定向(shell redirect)來把輸出保存到文件中。

還有一個常用選項是-n,它專門用於限制命令行是否產生輸出。使用-n選項後,只有末尾有“/p”選項的命令行才產生輸出,如:

$sed –n ‘s/pattern/substitute/p’ inputfile

該命令將會只輸出輸入文件改變的部分。

 

Awk的運行過程

Awk也可以用命令行或者腳本文件的方式處理單個或者多個文件:
$awk ‘指令’ 輸入文件
$awk –f 腳本文件輸入文件

Awk將每一行分解爲記錄,用空格或者製表符來區分記錄中的字段。它允許在任何過程中以任何方式訪問這些字段。$0表示整個記錄(行),$1、$2、……指向輸入行的各個字段。

如果沒有指定模式,則使用默認模式,即整個輸入文件。如:
$awk ‘{ print $1}’ phonelist.txt

就會輸出如下結果:(整個輸入文件的$1字段都輸出來了)
John
Jane
Jimmy

如果沒有給定處理過程,就使用默認處理print(打印),如:
$awk ‘/Jane/’ phonelist.txt

將會輸出:
Jane Doe, 100-555-2222, 100-555-1113,

正式用法是同時指定匹配模式和處理過程。讓我們用下面這條命令來輸出Jane的家庭電話號碼:
$awk ‘/jane/ { print $3}’ phonelist

這會輸出:
100-555-2222

我們可以通過用-F選項來選定任何我們喜歡的間隔符。因爲我們的輸入文件phonelist是用逗號來分隔的,所以我們需要用逗號來做分隔符。

命令如下:
$awk –F, ‘{print $1}’ phonelist.txt

這條命令將會輸出下列名字:
John Doe
Jane Doe
Jimmy Dean

如果我們想格式化輸出姓氏和名字,我們可以這麼做:
$awk –F, ‘{print $2 $1}’ phonelist.txt

結果是:
Doe, John
Doe, Jane
Dean, Jimmy

爲了達到一行只輸出一個字段的目的,我們可以用分號去分開打印語句,如:
$awk -F, '{ print $1; print $2; print $3; print $4 }' phonelist.txt


結果就會這樣:
John Doe
100-555-1111
100-555-1112

Jane Doe
100-555-2222
100-555-1113

Jimmy Dean
101-555-1111
101-555-2222

現在總結一下,sed主要用來改變數據;awk用來重新排列數據。通過sed和awk的高級編程可以採集到大量的信息。

 

http://www.newsmth.net/pc/pccon.php?id=2207&nid=82422

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章