sed
以行為單位處理檔案,awk
比sed
強的地方在於不僅能以行為單位還能以列為單位處理檔案。awk
預設的行分隔符是換行,預設的列分隔符是連續的空格和Tab,但是行分隔符和列分隔符都可以自定義,比如/etc/passwd
檔案的每一行有若干個欄位,欄位之間以:
分隔,就可以重新定義awk
的列分隔符為:
並以列為單位處理這個檔案。awk
實際上是一門很複雜的腳本語言,還有像C語言一樣的分支和循環結構,但是基本用法和sed
類似,awk
命令行的基本形式為:
awk option 'script' file1 file2 ... awk option -f scriptfile file1 file2 ...
和sed
一樣,awk
處理的檔案既可以由標準輸入重定向得到,也可以當命令行參數傳入,編輯命令可以直接當命令行參數傳入,也可以用-f
參數指定一個腳本檔案,編輯命令的格式為:
/pattern/{actions} condition{actions}
和sed
類似,pattern
是正則表達式,actions
是一系列操作。awk
程序一行一行讀出待處理檔案,如果某一行與pattern
匹配,或者滿足condition
條件,則執行相應的actions
,如果一條awk
命令只有actions
部分,則actions
作用於待處理檔案的每一行。比如檔案testfile
的內容表示某商店的庫存量:
ProductA 30 ProductB 76 ProductC 55
打印每一行的第二列:
$ awk '{print $2;}' testfile 30 76 55
自動變數$1
、$2
分別表示第一列、第二列等,類似於Shell腳本的位置參數,而$0
表示整個當前行。再比如,如果某種產品的庫存量低於75則在行末標註需要訂貨:
$ awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;}' testfile ProductA 30 REORDER ProductB 76 ProductC 55 REORDER
可見awk
也有和C語言非常相似的printf
函數。awk
命令的condition
部分還可以是兩個特殊的condition
-BEGIN
和END
,對於每個待處理檔案,BEGIN
後面的actions
在處理整個檔案之前執行一次,END
後面的actions
在整個檔案處理完之後執行一次。
awk
命令可以像C語言一樣使用變數(但不需要定義變數),比如統計一個檔案中的空行數
$ awk '/^ *$/ {x=x+1;} END {print x;}' testfile
就像Shell的環境變數一樣,有些awk
變數是預定義的有特殊含義的:
表 32.6. awk常用的內建變數
FILENAME | 當前輸入檔案的檔案名,該變數是隻讀的 |
NR | 當前行的行號,該變數是隻讀的,R 代表record |
NF | 當前行所擁有的列數,該變數是隻讀的,F 代表field |
OFS | 輸出格式的列分隔符,預設是空格 |
FS | 輸入檔案的列分融符,預設是連續的空格和Tab |
ORS | 輸出格式的行分隔符,預設是換行符 |
RS | 輸入檔案的行分隔符,預設是換行符 |
例如打印系統中的用戶帳號列表
$ awk 'BEGIN {FS=":"} {print $1;}' /etc/passwd
awk
還可以像C語言一樣使用if
/else
、while
、for
控制結構,此處從略。