awk提取命令詳解

本文出自http://hi.baidu.com/cjy2020/blog/item/b18c0587a0476026c65cc3c7.html,感受很好,因此轉載收藏

AWK 實用工具帶有其本身的 自包含語言,它不只是 Linux 中也是任何環境中現有 的功能最強大的數據處 理引擎之一。這種編程 及數據操做語言(其名 稱得自於它的創始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母)的最 大功能取決於一我的所 擁有的知識。它容許您 建立簡短的程序,這些 程序讀取輸入文件、爲 數據排序、處理數據、 對輸入執行計算以及生 成報表,還有無數其餘 的功能。

AWK 是什麼?

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

儘管操做可能會很複雜 ,但命令的語法始終是

awk '{pattern + action}' {filenames }

其中 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 讀取輸入內容時,整條 記錄被分配給變量 $0。每一個字段以字段 分隔符分開,被分配給 變量 $一、$二、$3 等等。一行在本質上可 以包含無數個字段,通 過字段號來訪問每一個字 段。所以,命令

awk '{print $1,$2,$3,$ 4,$5}' 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 $2,$3}' 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 $3,$2}' 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 $3,$2}' 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 $3,$2 ; print $4,$5}' emp_names
EVAN DULANEY
MOBILE AL
JEFF DURHAM
MOBILE AL
BILL STEEN
MOBILE AL
EVAN FELDMAN
MOBILE AL
STEVE SWIM
UNKNOWN AL
$

若是沒有使用分號 (print $3,$2,$4,$ 5),則會在同一行中 顯示全部內容。另外一方 面,若是分別給出兩個 打印語句,則會產生完 全不一樣的結果:

$ awk '/AL/ {print $3,$2} {print $4,$5}' 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 $3,$2 ; print $4", "$5" "}' emp_names
EVAN DULANEY
MOBILE, AL

JEFF DURHAM
MOBILE, AL

BILL STEEN
MOBILE, AL

EVAN FELDMAN
MOBILE, AL

STEVE SWIM
UNKNOWN, AL
$

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

* (換行)
* (製表)
* (退格)
* f(進紙)
* (回車)

所以,要讀取所有五個 最初由製表符分隔開的 字段,而且也利用製表 符打印它們,您能夠編 程以下

$ awk '{print $1" "$2" "$3" "$4" "$5}' 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 '$5 ˜ /AR/' emp_names
46019 BOGUE ROBERT PHOENIX AZ
46021 JUNE MICAH PHOENIX AZ
46022 KANE SHERYL UNKNOWN AZ
$

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

$ awk '$5 !˜ /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 $3,$2}

括號間的全部操做同時 發生。當使用多於一對 的括號時:

{print $3}{print $2}

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

$ awk '{print $3,$2}' 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 $3}{print $2}' 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:DULA NEY:EVAN:M OBILE:AL
46013:DURH AM:JEFF:MO BILE:AL
46015:STEE N:BILL:MOB ILE:AL
46017:FELD MAN:EVAN:M OBILE:AL
46018:SWIM :STEVE:UNK NOWN:AL
46019:BOGU E:ROBERT:P HOENIX:AZ
46021:JUNE :MICAH:PHO ENIX:AZ
46022:KANE :SHERYL:UN KNOWN:AR
46024:WOOD :WILLIAM:M UNCIE:IN
46026:FERG US:SARAH:M UNCIE:IN
46027:BUCK :SARAH:MUN CIE:IN
46029:TUTT LE:BOB:MUN CIE:IN
$

若是試圖經過指定所需 要的第二個字段來打印 姓氏

$ awk '{print $2}' emp_names

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

$ awk '{FS=":"}{ print $2}' emp_names

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

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

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

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

$ awk -F":" '{OFS="-"} {print $1,$2,$3,$ 4,$5}' emp_names
46012-DULA NEY-EVAN-M OBILE-AL
46013-DURH AM-JEFF-MO BILE-AL
46015-STEE N-BILL-MOB ILE-AL
46017-FELD MAN-EVAN-M OBILE-AL
46018-SWIM -STEVE-UNK NOWN-AL
46019-BOGU E-ROBERT-P HOENIX-AZ
46021-JUNE -MICAH-PHO ENIX-AZ
46022-KANE -SHERYL-UN KNOWN-AR
46024-WOOD -WILLIAM-M UNCIE-IN
46026-FERG US-SARAH-M UNCIE-IN
46027-BUCK -SARAH-MUN CIE-IN
46029-TUTT LE-BOB-MUN CIE-IN
$

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

$ awk -F":" '{print NR,$1,$2,$ 3}' 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 $1":"$2":" $3":"$4":" $5}' emp_names > new_emp_na mes

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

$ awk '$5 ~ /AL/ {print "NAME: "$2", "$3" CITY-STATE :
"$4", "$5" "}' 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 $1,"QTY: "$2,"PRICE : "$3,"TOTAL : "$2*$3}' 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 '{x=x+$2} {print x}' inventory
5
7
14
16
71
194
994
1074
1174
$

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

能夠應用相同的過程來 肯定現有庫存的總價值

$ awk '{x=x+($2* $3)} {print x}' inventory
39.95
99.93
125.06
133.24
198.69
2042.46
2194.46
2217.66
2241.66
$

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

$ awk '{x=x+($2* $3)}{print $1,"QTY: "$2,"PRICE : "$3,"TOTAL : "$2*$3,"BA L: "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 語句能夠分別指定在處 理實際開始以前或者完 成以後進行操做。BE GIN 語句最經常使用於創建變量 或顯示標題。另外一方面 ,END 語句可用於在程序結束 後繼續進行處理。

在前面的示例中,利用 如下例程生成了物品的 總價值:

awk '{x=x+($2* $3)} {print x}' inventory

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

$ awk '{x=x+($2* $3)} END {print "Total Value of Inventory: "x}' inventory
Total Value of Inventory: 2241.66
$

定義了變量 x,它對每一行進行處 理;可是,在全部處理 完成以前不會生成顯示 。儘管能夠做爲獨立例 程使用,它也能夠置入 到先前的代碼列表,添 加更多信息並生成更完 整的報表:

$ awk '{x=x+($2* $3)} {print $1,"QTY: "$2,"PRICE :
"$3,"TOTAL : "$2*$3} 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 $3,$2}'

awk 命令的輸入是排序操做 的輸出。除了 sort,還可使用 任何其餘的 Linux 命令 — 例如 grep。該過程容許 您在離開所選定字段前 對文件執行其餘操做。

相似於解釋程序,AW K 使用輸出改向操做符 > 和 >> 將其輸出放入文件中而 不是標準輸出設備。這 些符號的做用相似於它 們在解釋程序中的對應 符號,所以 > 在不存在文件時建立文 件,而 >> 追加到現有文件的尾部 。請看如下的示例:

$ awk '{print NR, $1 ) > "/tmp/file z" }' 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 $2 | "sort" }' emp_names
BOGUE
BUCK
DULANEY
DURHAM
FELDMAN
FERGUS
JUNE
KANE
STEEN
SWIM
TUTTLE
WOOD
$

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

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

$ cat awklist
{print $3,$2}
{print $4,$5," "}
$

$ 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 管理員所擁有的功能最 強大和靈活的工具之一 。經過了解其語言的一 些特性,您能夠開闢出 可以簡化任務的領域, 不然這些任務將會是非 常費時和困難的。
相關文章
相關標籤/搜索