shell編程下的AWK語法小結!

發表于:2007-05-25來源:作者:點擊數: 標簽:編程shellAWK實用工具小結
AWK 實用工具帶有其自己的自包含語言,它是 Unix /Linux 中也是任何環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操作語言(其名稱得自于它的創始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母)的最大功能取決于一個人
AWK 實用工具帶有其自己的自包含語言,它是Unix/Linux 中也是任何環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操作語言(其名稱得自于它的創始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母)的最大功能取決于一個人所擁有的知識。它允許您創建簡短的程序,這些程序讀取輸入文件、為數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。

MILY: Verdana,宋體, Verdana, Arial, Helvetica, sans-serif">

AWK 是什么?

最簡單地說,AWK 是一種用于處理文本的編程語言工具。AWK 實用工具的語言在很多方面類似于 shell 編程語言,盡管 AWK 具有完全屬于其本身的語法。在最初創造 AWK 時,其目的是用于文本處理,并且這種語言的基礎是,只要在輸入數據中有模式匹配,就執行一系列指令。該實用工具掃描文件中的每一行,查找與命令行中所給定內容相匹配的模式。如果發現匹配內容,則進行下一個編程步驟。如果找不到匹配內容,則繼續處理下一行。

盡管操作可能會很復雜,但命令的語法始終是:
awk '{pattern + action}'

其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令?;ɡㄌ?({}) 不需要在程序中始終出現,但它們用于根據特定的模式對一系列指令進行分組。

了解字段

實用工具將每個輸入行分為記錄和字段。記錄是單行的輸入,而每條記錄包含若干字段。默認的字段分隔符是空格或制表符,而記錄的分隔符是換行。雖然在默認情況下將制表符和空格都看作字段分隔符(多個空格仍然作為一個分隔符),但是可以將分隔符從空格改為任何其它字符。

為了進行演示,請查看以下保存為 emp_names 的員工列表文件:

46012   DULANEY     EVAN        MOBILE   AL
46013   DURHAM      JEFF        MOBILE   AL
46015   STEEN       BILL        MOBILE   AL
46017   FELDMAN     EVAN        MOBILE   AL
46018   SWIM        STEVE       UNKNOWN  AL
46019   BOGUE       ROBERT      PHOENIX  AZ
46021   JUNE        MICAH       PHOENIX  AZ
46022   KANE        SHERYL      UNKNOWN  AR
46024   WOOD        WILLIAM     MUNCIE   IN
46026   FERGUS      SARAH       MUNCIE   IN
46027   BUCK        SARAH       MUNCIE   IN
46029   TUTTLE      BOB         MUNCIE   IN


當 AWK 讀取輸入內容時,整條記錄被分配給變量 。每個字段以字段分隔符分開,被分配給變量 、、 等等。一行在本質上可以包含無數個字段,通過字段號來訪問每個字段。因此,命令
awk '{print ,,,,}' names

將會產生的打印輸出是

46012 DULANEY EVAN MOBILE AL
46013 DURHAM JEFF MOBILE AL
46015 STEEN BILL MOBILE AL
46017 FELDMAN EVAN MOBILE AL
46018 SWIM STEVE UNKNOWN AL
46019 BOGUE ROBERT PHOENIX AZ
46021 JUNE MICAH PHOENIX AZ
46022 KANE SHERYL UNKNOWN AR
46024 WOOD WILLIAM MUNCIE IN
46026 FERGUS SARAH MUNCIE IN
46027 BUCK SARAH MUNCIE IN
46029 TUTTLE BOB MUNCIE IN


值得注意的一項重要內容是,AWK 解釋由空格分隔的五個字段,但當它打印顯示內容時,在每個字段間只有一個空格。利用為每個字段指定了唯一號碼的功能,您可以選擇只打印特定的字段。例如,只打印每條記錄的姓名時,只需選擇第二個和第三個字段進行打?。?

$ awk '{print ,}' emp_names
DULANEY EVAN
DURHAM JEFF
STEEN BILL
FELDMAN EVAN
SWIM STEVE
BOGUE ROBERT
JUNE MICAH
KANE SHERYL
WOOD WILLIAM
FERGUS SARAH
BUCK SARAH
TUTTLE BOB
$


您還可以指定按任何順序打印字段,而無論它們在記錄中是如何存在的。因此,只需要顯示姓名字段,并且使其順序顛倒,先顯示名字再顯示姓氏:

$ awk '{print ,}' emp_names
EVAN DULANEY
JEFF DURHAM
BILL STEEN
EVAN FELDMAN
STEVE SWIM
ROBERT BOGUE
MICAH JUNE
SHERYL KANE
WILLIAM WOOD
SARAH FERGUS
SARAH BUCK
BOB TUTTLE
$

使用模式

通過包含一個必須匹配的模式,您可以選擇只對特定的記錄而不是所有的記錄進行操作。模式匹配的最簡單形式是搜索,其中要匹配的項目被包含在斜線 (/pattern/) 中。例如,只對那些居住在阿拉巴馬州的員工執行前面的操作:

$ awk '/AL/ {print ,}' emp_names
EVAN DULANEY
JEFF DURHAM
BILL STEEN
EVAN FELDMAN
STEVE SWIM
$


如果您不指定要打印的字段,則會打印整個匹配的條目:

$ awk '/AL/' emp_names
46012   DULANEY     EVAN     MOBILE     AL
46013   DURHAM      JEFF     MOBILE     AL
46015   STEEN       BILL     MOBILE     AL
46017   FELDMAN     EVAN     MOBILE     AL
46018   SWIM        STEVE    UNKNOWN    AL
$


對同一數據集的多個命令可以用分號 (;) 分隔開。例如,在一行中打印姓名,而在另一行中打印城市和州名:

$ awk '/AL/ {print , ; print ,}' emp_names
EVAN DULANEY
MOBILE AL
JEFF DURHAM
MOBILE AL
BILL STEEN
MOBILE AL
EVAN FELDMAN
MOBILE AL
STEVE SWIM
UNKNOWN AL
$


如果沒有使用分號 (print ,,,),則會在同一行中顯示所有內容。另一方面,如果分別給出兩個打印語句,則會產生完全不同的結果:

$ awk '/AL/ {print ,} {print ,}' emp_names
EVAN DULANEY
MOBILE AL
JEFF DURHAM
MOBILE AL
BILL STEEN
MOBILE AL
EVAN FELDMAN
MOBILE AL
STEVE SWIM
UNKNOWN AL
PHOENIX AZ
PHOENIX AZ
UNKNOWN AR
MUNCIE IN
MUNCIE IN
MUNCIE IN
MUNCIE IN
$


只有在列表中找到 AL 時才會給出字段三和字段二。但是,字段四和字段五是無條件的,始終打印它們。只有第一組花括號中的命令對前面緊鄰的命令 (/AL/) 起作用。

結果非常不便于閱讀,可以使其稍微更清晰一些。首先,在城市與州之間插入一個空格和逗號。然后,在每兩行顯示之后放置一個空行:

$ awk '/AL/ {print , ; print ", ""n"}' emp_names
EVAN DULANEY
MOBILE, AL

JEFF DURHAM
MOBILE, AL

BILL STEEN
MOBILE, AL

EVAN FELDMAN
MOBILE, AL

STEVE SWIM
UNKNOWN, AL
$


在第四和第五個字段之間,添加一個逗號和一個空格(在引號之間),在第五個字段后面,打印一個換行符 (n)。在 AWK 打印語句中還可以使用那些可在 echo 命令中使用的所有特殊字符,包括:

n(換行) 
t(制表) 
b(退格) 
f(進紙) 
r(回車)


因此,要讀取全部五個最初由制表符分隔開的字段,并且也利用制表符打印它們,您可以編程如下

$ awk '{print "t""t""t""t"}' emp_names
46012   DULANEY     EVAN     MOBILE    AL
46013   DURHAM      JEFF     MOBILE    AL
46015   STEEN       BILL     MOBILE    AL
46017   FELDMAN     EVAN     MOBILE    AL
46018   SWIM        STEVE    UNKNOWN   AL
46019   BOGUE       ROBERT   PHOENIX   AZ
46021   JUNE        MICAH    PHOENIX   AZ
46022   KANE        SHERYL   UNKNOWN   AR
46024   WOOD        WILLIAM  MUNCIE    IN
46026   FERGUS      SARAH    MUNCIE    IN
46027   BUCK        SARAH    MUNCIE    IN
46029   TUTTLE      BOB      MUNCIE    IN
$


通過連續設置多項標準并用管道 (|) 符號將其分隔開,您可以一次搜索多個模式匹配:

$ awk '/AL|IN/' emp_names
46012   DULANEY     EVAN     MOBILE    AL
46013   DURHAM      JEFF     MOBILE    AL
46015   STEEN       BILL     MOBILE    AL
46017   FELDMAN     EVAN     MOBILE    AL
46018   SWIM        STEVE    UNKNOWN   AL
46024   WOOD        WILLIAM  MUNCIE    IN
46026   FERGUS      SARAH    MUNCIE    IN
46027   BUCK        SARAH    MUNCIE    IN
46029   TUTTLE      BOB      MUNCIE    IN
$


這樣可找到每個阿拉巴馬州和印第安那州居民的匹配記錄。但是在試圖找出居住在亞利桑那州的人時,出現了一個問題:

$ awk '/AR/' emp_names
46019   BOGUE       ROBERT   PHOENIX   AZ
46021   JUNE        MICAH    PHOENIX   AZ
46022   KANE        SHERYL   UNKNOWN   AZ
46026   FERGUS      SARAH    MUNCIE    IN
46027   BUCK        SARAH    MUNCIE    IN
$


員工 46026 和 46027 沒有住在亞利桑那州;但是他們的名字中包含所搜索的字符序列。切記,當在 AWK 中進行模式匹配時,例如 grep、sed 或者大部分其他 Linux/Unix 命令,將在記錄(行)中的任何位置查找匹配,除非指定進行其他操作。為解決這一問題,必須將搜索與特定字段聯系起來。通過利用代字號 (?) 以及對特定字段的說明,可以達到這一目的,如下例所示:

$ awk ' ? /AR/' emp_names
46019   BOGUE       ROBERT   PHOENIX   AZ
46021   JUNE        MICAH    PHOENIX   AZ
46022   KANE        SHERYL   UNKNOWN   AZ
$


代字號(表示匹配)的對應符號是一個前面帶有感嘆號的代字號 (!?)。這些字符通知程序,如果搜索序列沒有出現在指定字段中,則找出與搜索序列相匹配的所有行:

$ awk ' !? /AR/' names
46012   DULANEY     EVAN     MOBILE    AL
46013   DURHAM      JEFF     MOBILE    AL
46015   STEEN       BILL     MOBILE    AL
46017   FELDMAN     EVAN     MOBILE    AL
46018   SWIM        STEVE    UNKNOWN   AL
46024   WOOD        WILLIAM  MUNCIE    IN
46026   FERGUS      SARAH    MUNCIE    IN
46027   BUCK        SARAH    MUNCIE    IN
46029   TUTTLE      BOB      MUNCIE    IN
$


在這種情況下,將顯示第五個字段中沒有 AR 的所有行 — 包括兩個 Sarah 條目,這兩個條目確實包含 AR,但卻是在第三個字段而不是第五個字段中。

花括號和字段分隔符

括號字符在 AWK 命令中起著很重要的作用。出現在括號之間的操作指出將要發生什么以及何時發生。當只使用一對括號時:
{print ,}

括號間的所有操作同時發生。當使用多于一對的括號時:
{print }{print }

執行第一組命令,在該命令完成后執行第二組命令。注意以下兩列清單的區別:

$ awk '{print ,}' names
EVAN DULANEY
JEFF DURHAM
BILL STEEN
EVAN FELDMAN
STEVE SWIM
ROBERT BOGUE
MICAH JUNE
SHERYL KANE
WILLIAM WOOD
SARAH FERGUS
SARAH BUCK
BOB TUTTLE
$

$ awk '{print }{print }' names
EVAN
DULANEY
JEFF
DURHAM
BILL
STEEN
EVAN
FELDMAN
STEVE
SWIM
ROBERT
BOGUE
MICAH
JUNE
SHERYL
KANE
WILLIAM
WOOD
SARAH
FERGUS
SARAH
BUCK
BOB
TUTTLE
$


要利用多組括號進行重復查找,執行第一組中的命令直到完成為止;然后處理第二組命令。如果有第三組命令,則在第二組命令完成后執行它,以此類推。在所生成的打印輸出中,有兩個分隔的打印命令,因此先執行第一個命令,隨后執行第二個命令,這樣導致每個條目顯示在兩行而不是一行中。

區分兩個字段的字段分隔符不一定始終是空格;它可以是任何可識別的字符。為進行演示,假定 emp_names 文件利用冒號而不是制表符來分隔字段:

$ cat emp_names
46012:DULANEY:EVAN:MOBILE:AL
46013:DURHAM:JEFF:MOBILE:AL
46015:STEEN:BILL:MOBILE:AL
46017:FELDMAN:EVAN:MOBILE:AL
46018:SWIM:STEVE:UNKNOWN:AL
46019:BOGUE:ROBERT:PHOENIX:AZ
46021:JUNE:MICAH:PHOENIX:AZ
46022:KANE:SHERYL:UNKNOWN:AR
46024:WOOD:WILLIAM:MUNCIE:IN
46026:FERGUS:SARAH:MUNCIE:IN
46027:BUCK:SARAH:MUNCIE:IN
46029:TUTTLE:BOB:MUNCIE:IN
$


如果試圖通過指定所需要的第二個字段來打印姓氏
$ awk '{print }' emp_names

您最后會得到十二個空行。因為文件中沒有空格,除了第一個字段之外沒有可認別的字段。為解決這一問題,必須通知 AWK 是空格之外的另一個字符作為分隔符,有兩種方法可通知 AWK 使用新的字段分隔符:使用命令行參數 -F,或在程序中指定變量 FS。兩種方法的效果相同,只有一種例外情況,如下例所示:

$ awk '{print }' emp_names

DURHAM
STEEN
FELDMAN
SWIM
BOGUE
JUNE
KANE
WOOD
FERGUS
BUCK
TUTTLE
$

$ awk -F: '{print }' emp_names
DULANEY
DURHAM
STEEN
FELDMAN
SWIM
BOGUE
JUNE
KANE
WOOD
FERGUS
BUCK
TUTTLE
$


在第一個命令中,頭一條記錄返回不正確的空行,而其他結果正確。直到讀取第二條記錄時,才識別字段分隔符并正確地執行。通過使用 BEGIN 語句可以糾正這一缺點(在后文詳述)。-F 的功能非常類似于 BEGIN,能夠正確地讀取第一條記錄并按要求執行。

在本文開始處我曾提到,默認的顯示/輸出字段分隔符是空格。通過使用輸出字段分隔符 (OFS) 變量,可以在程序中更改此特性。例如,要讀取文件(由冒號分隔)并以短劃線顯示,則命令是

$ awk -F":" '{print ,,,,}' emp_names
46012-DULANEY-EVAN-MOBILE-AL
46013-DURHAM-JEFF-MOBILE-AL
46015-STEEN-BILL-MOBILE-AL
46017-FELDMAN-EVAN-MOBILE-AL
46018-SWIM-STEVE-UNKNOWN-AL
46019-BOGUE-ROBERT-PHOENIX-AZ
46021-JUNE-MICAH-PHOENIX-AZ
46022-KANE-SHERYL-UNKNOWN-AR
46024-WOOD-WILLIAM-MUNCIE-IN
46026-FERGUS-SARAH-MUNCIE-IN
46027-BUCK-SARAH-MUNCIE-IN
46029-TUTTLE-BOB-MUNCIE-IN
$


FS 和 OFS 是(輸入)字段分隔符和輸出字段分隔符,它們只是一對可以在 AWK 實用工具中使用的變量。例如,要在打印時為每行編號,可以采用以下方式使用 NR 變量:

$ awk -F":" '{print NR,,,}' emp_names
1 46012 DULANEY EVAN
2 46013 DURHAM JEFF
3 46015 STEEN BILL
4 46017 FELDMAN EVAN
5 46018 SWIM STEVE
6 46019 BOGUE ROBERT
7 46021 JUNE MICAH
8 46022 KANE SHERYL
9 46024 WOOD WILLIAM
10 46026 FERGUS SARAH
11 46027 BUCK SARAH
12 46029 TUTTLE BOB
$


找出員工號碼處于 46012 和 46015 之間的所有行:

$ awk -F":" '/4601[2-5]/' emp_names
46012   DULANEY EVAN  MOBILE AL
46013   DURHAM  JEFF  MOBILE AL
46015   STEEN   BILL  MOBILE AL
$


添加文本

可以按照添加控制序列或其他字符的相同方式將文本添加到顯示中。例如,要將分隔符從空格改為冒號,則命令是
awk '{print ":"":"":"":"}' emp_names > new_emp_names

在這種情況下,字符 (:) 包含在引號 ("/") 中,它被添加到每個字段之間。在引號之間的值可以是任何內容。例如,創建一個關于居住在阿拉巴馬州的員工的外觀類似數據庫的顯示:

$ awk ' ~ /AL/ {print "NAME: "", ""nCITY-STATE:
"", ""n"}' emp_names

NAME: DULANEY, EVAN
CITY-STATE: MOBILE, AL

NAME: DURHAM, JEFF
CITY-STATE: MOBILE, AL

NAME: STEEN, BILL
CITY-STATE: MOBILE, AL

NAME: FELDMAN, EVAN
CITY-STATE: MOBILE, AL

NAME: SWIM, STEVE
CITY-STATE: UNKNOWN, AL
$


數學操作

AWK 除了提供文本功能,還提供全部范圍的算術操作符,包括以下符號:

+ 將數字相加
- 減
* 乘
/ 除
^ 執行指數運算
% 提供模
++ 將變量值加一
+= 將其他操作的結果分配給變量
— 將變量減一
-= 將減法操作的結果分配給變量
*= 分配乘法操作的結果
/= 分配除法操作的結果
%= 分配求模操作的結果


例如,假定您的機器上存在以下的文件,詳細地列出硬件商店中的物品:

$ cat inventory
hammers 5       7.99
drills  2      29.99
punches 7       3.59
drifts  2       4.09
bits   55       1.19
saws  123      14.99
nails 800        .19
screws 80        .29
brads 100        .24
$


第一項業務定單是通過將第二個字段(數量)的值乘以第三個字段(價格)的值,計算每種物品的庫存價值:

$ awk '{print ,"QTY: ","PRICE: ","TOTAL: "*}' inventory
hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77
nails QTY: 800 PRICE: .19 TOTAL: 152
screws QTY: 80 PRICE: .29 TOTAL: 23.2
brads QTY: 100 PRICE: .24 TOTAL: 24
$


如果這些行本身并不重要,您只是希望確定商店中有多少件物品,則可以分配一個普通變量,按照每條記錄中的物品數量增加:

$ awk ' {print x}' inventory
5
7
14
16
71
194
994
1074
1174
$


根據這一數據,商店中有 1174 件物品。第一次執行時,變量 x 沒有值,因此它采用第一行第二個字段的值。第二次執行時,它保留了第一行的值并加上第二行的值,以此類推,直到達到累計的總合。

可以應用相同的過程來確定現有庫存的總價值:

$ awk ' {print x}' inventory
39.95
99.93
125.06
133.24
198.69
2042.46
2194.46
2217.66
2241.66
$


因此,1174 件物品的價值是 ,241.66。雖然這一過程可以獲得總計值,但它的外觀很差,需要加工成實際的報表。利用一些附加項,很容易使顯示變得更整潔:

$ awk '{print ,"QTY: ","PRICE: ","TOTAL: "*,"BAL: "x}' inventory
hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95 BAL: 39.95
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98 BAL: 99.93
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13 BAL: 125.06
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18 BAL: 133.24
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45 BAL: 198.69
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77 BAL: 2042.46
nails QTY: 800 PRICE: .19 TOTAL: 152 BAL: 2194.46
screws QTY: 80 PRICE: .29 TOTAL: 23.2 BAL: 2217.66
brads QTY: 100 PRICE: .24 TOTAL: 24 BAL: 2241.66
$


該過程提供了每條記錄的清單,同時將總價值分配給庫存值,并保持商店資產的運作平衡。

BEGIN 和 END

使用 BEGIN 和 END 語句可以分別指定在處理實際開始之前或者完成之后進行操作。BEGIN 語句最常用于建立變量或顯示標題。另一方面,END 語句可用于在程序結束后繼續進行處理。

在前面的示例中,利用以下例程生成了物品的總價值:
awk ' {print x}' inventory

該例程在運行總計累加時顯示了文件中的每一行。沒有其他方法可以指定它,而不讓在每一行進行打印也導致它始終不打印出來。但是,利用 END 語句可以避免這一問題:

$ awk ' END {print "Total Value of Inventory:"x}' inventory
Total Value of Inventory: 2241.66
$


定義了變量 x,它對每一行進行處理;但是,在所有處理完成之前不會生成顯示。盡管可以作為獨立例程使用,它也可以置入到先前的代碼列表,添加更多信息并生成更完整的報表:

$ awk ' {print ,"QTY: ","PRICE: 
    ","TOTAL: "*} END {print "Total Value of Inventory: " x}' inventory

hammers QTY: 5 PRICE: 7.99 TOTAL: 39.95
drills QTY: 2 PRICE: 29.99 TOTAL: 59.98
punches QTY: 7 PRICE: 3.59 TOTAL: 25.13
drifts QTY: 2 PRICE: 4.09 TOTAL: 8.18
bits QTY: 55 PRICE: 1.19 TOTAL: 65.45
saws QTY: 123 PRICE: 14.99 TOTAL: 1843.77
nails QTY: 800 PRICE: .19 TOTAL: 152
screws QTY: 80 PRICE: .29 TOTAL: 23.2
brads QTY: 100 PRICE: .24 TOTAL: 24
Total Value of Inventory: 2241.66
$


BEGIN 命令與 END 的工作方式相同,但它建立了那些需要在完成其他工作之前所做的項目。該過程最常見的目的是創建報表的標題。此例程的語法類似于
$ awk 'BEGIN {print "ITEM QUANTITY PRICE TOTAL"}'

輸入、輸出和源文件

AWK 工具可以從文件中讀取其輸入,正如在此之前所有示例所做的那樣,它也可以從其他命令的輸出中獲取輸入。例如:
$ sort emp_names | awk '{print ,}'
awk 命令的輸入是排序操作的輸出。除了 sort,還可以使用任何其他的 Linux 命令 — 例如 grep。該過程允許您在離開所選定字段前對文件執行其他操作。

類似于解釋程序,AWK 使用輸出改向操作符 > 和 >> 將其輸出放入文件中而不是標準輸出設備。這些符號的作用類似于它們在解釋程序中的對應符號,因此 > 在不存在文件時創建文件,而 >> 追加到現有文件的尾部。請看以下的示例:

$ awk '{print NR,  ) > "/tmp/filez" }' emp_names
$ cat /tmp/filez
1	46012
2	46013
3	46015
4	46017
5	46018
6	46019
7	46021
8	46022
9	46024
10	46026
11	46027
12	46029
$


檢查該語句的語法,您會看到輸出改向是在打印語句完成后進行的。必須將文件名包含在引號中,否則它只是一個未初始化的 AWK 變量,而將指令聯接起來會在 AWK 中產生錯誤。(如果不正確地使用改向符號,則 AWK 無法了解該符號意味著“改向”還是一個關系操作符。)

在 AWK 中輸出到管道也類似于解釋程序中所實現的相同操作。要將打印命令的輸出發送到管道中,可以在打印命令后附加管道符號以及命令的名稱,如下所示:

$ awk '{ print  | "sort" }' emp_names
BOGUE
BUCK
DULANEY
DURHAM
FELDMAN
FERGUS
JUNE
KANE
STEEN
SWIM
TUTTLE
WOOD
$


這是輸出改向的情況,必須將命令包含在引號中,而管道的名稱是被執行命令的名稱。

AWK 所使用的命令可以來自兩個地方。首先,可以在命令行中指定它們,如示例中所示。其次,它們可以由源文件提供。如果是這種情況,通過 -f 選項將這種情況向 AWK 發出警告。演示如下:

$ cat awklist
{print ,}
{print ,,"n"}
$

$ awk -f awklist emp_names
EVAN DULANEY
MOBILE AL

JEFF DURHAM
MOBILE AL

BILL STEEN
MOBILE AL

EVAN FELDMAN
MOBILE AL

STEVE SWIM
UNKNOWN AL

ROBERT BOGUE
PHOENIX AZ

MICAH JUNE
PHOENIX AZ

SHERYL KANE
UNKNOWN AR

WILLIAM WOOD
MUNCIE IN

SARAH FERGUS
MUNCIE IN

SARAH BUCK
MUNCIE IN

BOB TUTTLE
MUNCIE IN

$


注意,在源文件中的任何地方或者在命令行中調用它時,不使用單引號。單引號只用于區別命令行中的命令與文件名稱。

如果簡單的輸出不能處理您的程序中所需要的復雜信息,則可以嘗試由 printf 命令獲得的更加復雜的輸出,其語法是
printf( format, value, value ...)

該語法類似于 C 語言中的 printf 命令,而格式的規格是相同的。通過插入一項定義如何打印數值的規格,可以定義該格式。格式規格包含一個跟有字母的 %。類似于打印命令,printf 不必包含在圓括號中,但是可以認為使用圓括號是一種良好的習慣。

下表列出 printf 命令提供的各種規格。

規格 說明 
%c 打印單個 ASCII 字符 
%d 打印十進制數 
%e 打印數字的科學計數表示 
%f 打印浮點表示 
%g 打印 %e 或 %f;兩種方式都更簡短 
%o 打印無符號的八進制數 
s 打印 ASCII 字符串 
%x 打印無符號的十六進制數 
%% 打印百分號;不執行轉換


可以在 % 與字符之間提供某些附加的格式化參數。這些參數進一步改進數值的打印方式:

參數 說明
- 將字段中的表達式向左對齊
,width 根據需要將字段補齊到指定寬度(前導零使用零將字段補齊)
.prec 小數點右面數字的最大字符串寬度或最大數量

printf 命令能夠控制并將數值從一種格式轉換為另一種格式。當需要打印變量的值時,只需提供一種規格,指示 printf 如何打印信息(通常包含在雙引號中)即可。必須為每個傳遞到 printf 的變量包含一個規格參數;如果包含過少的參數,則 printf 不會打印所有的數值。

處理錯誤

AWK 工具報告所發生錯誤的方式很令人惱火。一個錯誤會阻礙任何操作的進行,所提供的錯誤信息非常含混不清:
awk: syntax error near line 2
awk: bailing out near line 2

您可能會花幾小時的時間查看第 2 行,試圖找出它為什么阻礙程序運行;這就是支持使用源文件的一個有力論據。

切記有兩條規則可以幫助您避免出現語法錯誤:
1. 確保命令位于括號中,而括號位于單引號中。沒有使用這些字符之一必然導致程序無法運行。
2. 搜索命令需要位于斜線之間。要找出住在印第安那州的員工,您必須使用“/IN/”而不是“IN”。

結論

盡管 AWK 完全代表另外的含意,但它應該是管理員智能工具包的首字母縮寫。連同 SED 一起,AWK 實用工具是 Linux 管理員所擁有的功能最強大和靈活的工具之一。通過了解其語言的一些特性,您可以開辟出能夠簡化任務的領域,否則這些任務將會是非常費時和困難的。

關于作者

Emmett Dulaney (edulaney@iquest.net) 獲得了 18 種供應商認證。他編寫了數本關于 Linux、UNIX 和認證研究的書籍,并在許多會議上進行了演講,而且他是 Mercury Technical Solutions 的前合作伙伴。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97