shell中awk詳解 (模式提取) shell
您正在學習 Linux 嗎?本文對於很是有用的 AWK 文本操做工具進行了介紹,很是有價值。 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: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 $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-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,$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_names 在這種狀況下,字符 (:) 包含在引號 ("/") 中,它被添加到每一個字段之間。在引號之間的值能夠是任何內容。例如,建立一個關於居住在阿拉巴馬州的員工的外觀相似數據庫的顯示: $ 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,"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 '{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。該過程容許您在離開所選定字段前對文件執行其餘操做。 相似於解釋程序,AWK 使用輸出改向操做符 > 和 >> 將其輸出放入文件中而不是標準輸出設備。這些符號的做用相似於它們在解釋程序中的對應符號,所以 > 在不存在文件時建立文件,而 >> 追加到現有文件的尾部。請看如下的示例: $ awk '{print NR, $1 ) > "/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 $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 管理員所擁有的功能最強大和靈活的工具之一。經過了解其語言的一些特性,您能夠開闢出可以簡化任務的領域,不然這些任務將會是很是費時和困難的。