awk 非常擅長處理結構化數(shù)據(jù)和生成表單。和 sed 和 grep 很相似。由于 awk 具備各種及哦啊本語言的特點,所以可以把它看做是一種腳本語言。
先來看個案例,只查看 /etc/passwd/ 目錄下的用戶名和組名
awk -F: ‘{print $1,$5}’ /etc/passwd
意思是: 使用: 來分割這一行,把這一行的第一和第五個字段打印出來。
調用 awk
awk [-F 分隔符] 'commands' input-file(s)
這里的 commands
是真正的 awk
命令,[-F 分隔符] 適可選的,awk
默認使用空格分隔,因此如果要瀏覽域間有空格的文本,不必指定這個選項,但如果瀏覽如 passwd 文件,此文件各域使用冒號作為分隔符,則必須使用 -F
選項: awk -F : 'commands' input-file
awk
命令插入一個文件,并使 awk
程序可執(zhí)行,然后用 awk
命令解釋器作為腳本的首行,以便通過鍵入腳本名稱來調用它awk
命令插入一個單獨文件,然后調用,如: awk -f awk-script-file input-file-f
選項指明在文件 awk-script-file
的 awk
腳本,input-file
是使用 awk
進行瀏覽的文件名任何 awk
語句都是由模式和動作組成,在一個 awk
腳本中可能有許多語句。模式部分決定動作語句何時觸發(fā)及觸發(fā)事件。動作即對數(shù)據(jù)進行的操作,如果省去模式部分,動作將時刻保持執(zhí)行狀態(tài)。
模式可以是任何條件語句或復合語句或正則表達式,模式包含兩個特殊字段 BEGIN
和 END
,使用 BEGIN 語句設置計數(shù)和打印頭,BEGIN
語句使用在任何文本瀏覽動作之前,之后文本瀏覽動作依據(jù)輸入文件開始執(zhí)行;END
語句用來在 awk
完成文本瀏覽動作后打印輸出文本總數(shù)和結尾狀態(tài)標志,有動作必須使用 {} 括起來
實際動作在大括號 {} 內指明,常用來做打印動作,但是還有更長的代碼如 if
和循環(huán) looping
語句及循環(huán)退出等,如果不指明采取什么動作,awk
默認打印出所有瀏覽出的記錄
awk
執(zhí)行時,其瀏覽標記為 $1,$2...$n
,這種方法稱為域標記。使用 $1,$3
表示參照第 1 和第 3 域,注意這里使用逗號分隔域,使用 $0
表示使用所有域。例
awk -F :‘{print $0}’ /etc/passwd
// 表示打印所有域并把結果重定向到 /etc/passwd 中 (所謂的域就是某一行中的字段)
awk -F : ‘{print $0}’ /etc/passwd
/// 在屏幕上顯示出來
awk ‘{print $1,$4}’ /etc/passwd
// 只打印第一和第四域 (第一和第四字段)
awk -F: ‘BRGIN{print”hahaha\n---”}{print $1 “\t” $4}’ /etc/passwd
// 表示打印頭信息,在輸入的內容的第一行前加上”hahaha”,同時內容之間用 tab 鍵分開。
awk -F: 'BEGIN{print"hahaha\n---"}{print $1"\t"$4}END{print"end\n"}' /etc/passwd
// 這個代表的意思是說打印開頭結尾awk 的條件匹配符
<、<=、==、!=、>=、~ 匹配正則表達式、!~ 不匹配正則表達式
awk -F: '{if($1~/root/)print $0}' /etc/passwd
// 在 /etc/passwd 這個文件中,如果某條記錄的第一個字段含有 root 就打印整條記錄到屏幕上,注意,只要包含就行。awk -F: '$1=="root"{print $0}' /etc/passwd
// 某行中的第一個字段必須等于 root 才打印。awk -F: '$0!~"root"{print $0}' /etc/passwd
打印整條不包含 root 的記錄,使用雙引號或者反斜杠都是一樣的。其他的操作符具體不在介紹。
awk 的設計目的就是操作記錄與字段:awk 讀取輸入記錄 (通常是一些行),然后自動將各個記錄且分為字段。awk 將每條記錄內的字段樹木,存儲到內建變量 NF。通過上面的例子,差不多已經(jīng)總體上有了一定得了解:awk '{print $NF}'
打印最后一行,比較特殊的字段是編號 0,表示整條記錄。
awk 內置變量
ARGC 命令行參數(shù)個數(shù)
ARGV 命令行參數(shù)排列
ENVIRON 支持隊列中系統(tǒng)環(huán)境變量的使用
FILENAME awk 瀏覽的文件名
FNR 瀏覽文件的記錄數(shù)
FS 設置輸入域分隔符,等價于命令行 -F 選項
NF 瀏覽記錄的域的個數(shù)
NR 已讀的記錄數(shù)
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
案例
統(tǒng)計 /etc/passwd
: 文件名,每行的行號,每行的列數(shù),對應的完整行內容:
awk -F ':' '{print"filename:"FILENAME",linenumber:"NR",columns:"NF",linecontent:"$0}' /etc/passwd
除了 awk 的內置變量,awk 還可以自定義變量。
例如:
統(tǒng)計 /etc/passwd
的行數(shù)
awk '{count++}END{print count}' /etc/passwd
count 是自定義變量,這里沒有初始化 count,雖然默認是 0,但是妥當?shù)淖龇ㄟ€是初始化為 0。
awk 'BEGIN{count=0}{count=count+1}END{print count}' /etc/passwd
例如:
統(tǒng)計某個文件夾下的文件占用的字節(jié)數(shù)
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print"[end]size is ",size}'
如果按照 M 為單位顯示
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print"[end]size is ",size/1024/1024,"M"}'
小結:
sed
是處理簡單字符串替換的主要工具。大部分 shell 腳本在使用 sed
時幾乎都是用來做替換的操作。sed,awk
或其他交互式文本編輯程序時,這個法則相當重要。awk
多半用于簡單的“單命令行程序”,當你想要只顯示選定的字段,或是重新安排行內的字段順序時,就是 awk
排上用場的時候了。由于 awk
還是編程語言,即使在尖端的程序里,他也能發(fā)揮強大的作用。