?開(kāi)篇語(yǔ):
在 Linux 命令中,?
?awk?
??是一個(gè)處理文件中的數(shù)據(jù)的高級(jí)工具,它能提供一個(gè)類編程環(huán)境來(lái)修改和重新組織文件中的數(shù)據(jù)。
特別說(shuō)明:
?GNU gawk
?
?awk?
??既是一個(gè)命令,也是一種程序語(yǔ)言,它可以有不同的實(shí)現(xiàn)版本。在 Linux 系統(tǒng)中,?
?awk?
??的實(shí)現(xiàn)版本是 GNU gawk。在 shell 中執(zhí)行???awk?
??命令,實(shí)際執(zhí)行的是???gawk?
??命令。
如此截圖:
?所以下文中所說(shuō)的gawk也就是我們常稱呼的awk。
一、初始gawkgawk 程序讓流編輯邁上了一個(gè)新的臺(tái)階,它提供了一種編程語(yǔ)言而不只是編輯器命令。
gawk 功能概述:
- 定義變量來(lái)保存數(shù)據(jù);
- 使用算術(shù)和字符串操作符來(lái)處理數(shù)據(jù);
- 使用結(jié)構(gòu)化編程概念(比如if-then語(yǔ)句和循環(huán))來(lái)為數(shù)據(jù)處理增加處理邏輯;
- 通過(guò)提取數(shù)據(jù)文件中的數(shù)據(jù)元素,將其重新排列或格式化,生成格式化報(bào)告。
1.1 gawk 的命令格式?
?gawk的命令格式:
gawk options program file
參數(shù)選項(xiàng):
- -F fs? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 指定行中劃分?jǐn)?shù)據(jù)字段的字段分隔符
- -f file? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 從指定的文件中讀取程序
- -v var=value? ? ? ? ? ? ? ? ? 定義gawk程序中的一個(gè)變量及其默認(rèn)值
- -mf N? ? ? ? ? ? ? ? ? ? ? ? ? ? ?指定要處理的數(shù)據(jù)文件中的最大字段數(shù)
- -mr N? ? ? ? ? ? ? ? ? ? ? ? ? ? ?指定數(shù)據(jù)文件中的最大數(shù)據(jù)行數(shù)
- -W keyword? ? ? ? ? ? ? ? ? ?指定gawk的兼容模式或警告等級(jí)
實(shí)戰(zhàn)說(shuō)明:
命令行選項(xiàng)提供了一個(gè)簡(jiǎn)單的途徑來(lái)定制 gawk 程序中的功能。我們會(huì)在探索 gawk 時(shí)進(jìn)一步
了解這些選項(xiàng)。
gawk 的強(qiáng)大之處在于程序腳本。可以寫(xiě)腳本來(lái)讀取文本行的數(shù)據(jù),然后處理并顯示數(shù)據(jù),創(chuàng)
建任何類型的輸出報(bào)告。
1.2 從命令行讀取程序腳本
gawk程序腳本用一對(duì)花括號(hào)來(lái)定義。你必須將腳本命令放到兩個(gè)花括號(hào){}中。由于gawk命令行假定腳本是單個(gè)文本字符串,還必須將腳本命令放到單引號(hào)中。
簡(jiǎn)單的示例:
?命令解說(shuō):
? ? ?如果你操作這個(gè)示例在你的服務(wù)器終端,你會(huì)發(fā)現(xiàn),并沒(méi)有任何結(jié)果輸出,而當(dāng)你隨意輸入一個(gè)數(shù)字或者字符串的時(shí)候會(huì)發(fā)現(xiàn)都會(huì)返回 同一個(gè)結(jié)果,這個(gè)原因就在于沒(méi)有在命令行上指 定文件名,所以gawk程序會(huì)從STDIN接收數(shù)據(jù)。在運(yùn)行這個(gè)程序時(shí),它會(huì)一直等待從STDIN輸入 的文本。 如果你輸入一行文本并按下回車(chē)鍵,gawk會(huì)對(duì)這行文本運(yùn)行一遍程序腳本。和??sed??編輯器一 樣,gawk程序會(huì)針對(duì)數(shù)據(jù)流中的每行文本執(zhí)行程序腳本。由于程序腳本被設(shè)為顯示一行固定的文 本字符串,因此不管你在數(shù)據(jù)流中輸入什么文本,都會(huì)得到同樣的文本輸出。
1.3 使用數(shù)據(jù)字段變量
gawk 的主要特性之一是其處理文本文件中數(shù)據(jù)的能力。它會(huì)自動(dòng)給一行中的每個(gè)數(shù)據(jù)元素分
配一個(gè)變量。默認(rèn)情況下, gawk會(huì)將如下變量分配給它在文本行中發(fā)現(xiàn)的數(shù)據(jù)字段,而且在文本行中,每個(gè)數(shù)據(jù)字段都是通過(guò)字段分隔符劃分的。gawk在讀取一行文本時(shí),會(huì)用預(yù)定義的字段分隔符劃分每個(gè)數(shù)據(jù)字段。gawk中默認(rèn)的字段分隔符是任意的空白字符。
數(shù)據(jù)字段釋義:
- $0代表整個(gè)文本行;
- $1代表文本行中的第1個(gè)數(shù)據(jù)字段;
- $2代表文本行中的第2個(gè)數(shù)據(jù)字段;
- $n代表文本行中的第n個(gè)數(shù)據(jù)字段。
操作示例:
a.顯示第1個(gè)數(shù)據(jù)字段的值
?
1.4 在腳本程序中使用多個(gè)命令
gawk 編程語(yǔ)言支持將多條 命令組合成一個(gè)正常的程序。要在命令行上的程序腳本中使用多條命令,只要在命令之間放個(gè)分號(hào)即可。
操作示例:
?
?命令詳解:
第一條命令會(huì)給字段變量 $4 賦值。第二條命令會(huì)打印整個(gè)數(shù)據(jù)字段。注意, gawk 程序在輸
出中已經(jīng)將原文本中的第四個(gè)數(shù)據(jù)字段替換成了新值。
?1.5?從文件中讀取程序
gawk編輯器支持將程序存儲(chǔ)到文件中,然后再在命令行中引用。
a 操作示例:
?
?命令詳解:
應(yīng)用腳本文件只需要使用 -f 參數(shù)即可,此示例程序腳本會(huì)使用print命令輸出/etc/passwd文件的主目錄數(shù)據(jù)字段(字段變 量$6),以及userid數(shù)據(jù)字段(字段變量$1)。
程序文件中也可以指定多條命令。只需要一條命令放一行即可,不需要用分號(hào)。
b操作示例:
?
1.6 處理數(shù)據(jù)前運(yùn)行腳本
gawk 允許指定程序腳本何時(shí)運(yùn)行。默認(rèn)情況下, gawk 會(huì)從輸入中讀取一行文本,然后針對(duì)該行的數(shù)據(jù)執(zhí)行程序腳本。有時(shí)可能需要在處理數(shù)據(jù)前運(yùn)行腳本,此時(shí)需要用到關(guān)鍵字BEGIN ,它會(huì)強(qiáng)制gawk 在讀取數(shù)據(jù)前執(zhí)行 BEGIN 關(guān)鍵字后指定的程序腳本。
?
可以看到此時(shí)我們沒(méi)有輸入文本內(nèi)容同樣可以輸出內(nèi)容,當(dāng)然這種單一的使用是不常用的,工作中我們常常是結(jié)合其他命令,此時(shí)的名利格式是這樣的:
??命令解說(shuō):
此時(shí)我們?cè)贐EGIN腳本區(qū)域后用 { } 定義一個(gè)新的腳本區(qū)域,這個(gè)腳本區(qū)域的程序會(huì)相繼執(zhí)行。值得注意的是,不管后面有幾個(gè)腳本區(qū)域,他們都需要包含在同一個(gè)單引號(hào)之中。
?1.7 在處理數(shù)據(jù)后運(yùn)行腳本
與BEGIN對(duì)應(yīng),END關(guān)鍵字允許指定一個(gè)程序腳本,gawk會(huì)在讀完數(shù)據(jù)后執(zhí)行它。
演示截圖:
?
?命令解說(shuō):
當(dāng) gawk 程序輸出完文件所有內(nèi)容后,執(zhí)行 END 腳本中的命令。
?小小趣味實(shí)戰(zhàn):
腳本內(nèi)容:
BEGIN {
print "The latest list of users and shells"
print " UserID Shell"
print "-------- -------"
FS=":"
}
{
print $1 " " $7
}
END {
print "This concludes the listing"
}
演示截圖(結(jié)尾部分有做刪節(jié))?
?
?說(shuō)明:
二 、gawk 變量的使用這個(gè)腳本定義了一個(gè)叫作FS的特殊變量。這是定義 字段分隔符的另一種方法。這樣你就不用依靠腳本用戶在命令行選項(xiàng)中定義字段分隔符了。
gawk支持兩種類型的變量:
- 內(nèi)建變量
- 自定義變量
2.1 gawk 內(nèi)建變量
gawk 程序使用內(nèi)建變量來(lái)引用程序數(shù)據(jù)里的一些特殊功能。
2.1.1?字段和記錄分隔符變量
數(shù)據(jù)字段變量:
引用記錄中的第一個(gè)數(shù)據(jù)字段,就用變量$1 ;要引用第二個(gè)字段,就用 $2 ,依次類推。
gawk命令可以在命令行下使用參數(shù) -F 或者在 gawk 程序中使用特殊的內(nèi)建變量FS 來(lái)更改字段分隔符。內(nèi)建變量FS是一組內(nèi)建變量中的一個(gè),這組變量用于控制gawk如何處理輸入輸出數(shù)據(jù)中的
字段和記錄。如下是常用的一些內(nèi)置變量:
- FIELDWIDTHS ? ? ? ? ? ? ?由空格分隔的一列數(shù)字,定義了每個(gè)數(shù)據(jù)字段確切寬度
- FS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸入字段分隔符
- RS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸入記錄分隔符
- OFS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?輸出字段分隔符
- ORS ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??輸出記錄分隔符
A:核心說(shuō)明
OFS和FS都 定義了 gawk如何處理數(shù)據(jù)流中的數(shù)據(jù)字段,區(qū)別在于,OFS是使用在 print命令的輸出上。默認(rèn)情況下, gawk 將OFS設(shè)成一個(gè)空格。
?
print 命令會(huì)自動(dòng)將 OFS 變量的值放置在輸出中的每個(gè)字段間。通過(guò)設(shè)置 OFS 變量,可以在輸出中使用任意字符串來(lái)分隔字段。
FIELDWIDTHS 變量允許你不依靠字段分隔符來(lái)讀取記錄。在一些應(yīng)用程序中,數(shù)據(jù)并沒(méi)有使用字段分隔符,而是被放置在了記錄中的特定列。這種情況下,必須設(shè)定FIELDWIDTHS 變量來(lái)匹配數(shù)據(jù)在記錄中的位置。
?說(shuō)明:
FIELDWIDTHS 變量定義了四個(gè)字段, gawk 依此來(lái)解析數(shù)據(jù)記錄。每個(gè)記錄中的數(shù)字串會(huì)根
據(jù)已定義好的字段長(zhǎng)度來(lái)分割。
B:核心說(shuō)明
變量 RS 和 ORS 定義了 gawk 程序如何處理數(shù)據(jù)流中的字段。默認(rèn)情況下, gawk 將 RS 和 ORS 設(shè)為換行符。默認(rèn)的RS 值表明,輸入數(shù)據(jù)流中的每行新文本就是一條新紀(jì)錄。
?示例截圖:
?命令解說(shuō):
該示例中 把 FS變量設(shè)置成換行符。這就表明數(shù)據(jù)流中的每行都是一個(gè)單獨(dú)的字 段,每行上的所有數(shù)據(jù)都屬于同一個(gè)字段。把 RS 變量設(shè)置成空字符串,然后在數(shù)據(jù)記錄間留一個(gè)空白行。 gawk 會(huì)把每個(gè)空白行當(dāng)作一個(gè)記錄分隔符。
2.1.2 數(shù)據(jù)變量
常用變量如下:
- ARGC ?? ??? ? 當(dāng)前命令行參數(shù)個(gè)數(shù)
- ARGIND ?? ??? ? 當(dāng)前文件在ARGV中的位置
- ARGV ?? ??? ? 包含命令行參數(shù)的數(shù)組
- CONVFMT?? ??? ? 數(shù)字的轉(zhuǎn)換格式(參見(jiàn)printf語(yǔ)句),默認(rèn)值為%.6 g
- ENVIRON ?? ? 當(dāng)前shell環(huán)境變量及其值組成的關(guān)聯(lián)數(shù)組
- ERRNO ?? ??? ? 當(dāng)讀取或關(guān)閉輸入文件發(fā)生錯(cuò)誤時(shí)的系統(tǒng)錯(cuò)誤號(hào)
- FILENAME ? ? 用作gawk輸入數(shù)據(jù)的數(shù)據(jù)文件的文件名
- FNR ? ? ? ? ?當(dāng)前數(shù)據(jù)文件中的數(shù)據(jù)行數(shù)
- IGNORECASE ? 設(shè)成非零值時(shí),忽略gawk命令中出現(xiàn)的字符串的字符大小寫(xiě)
- NF ? ? ? ? ? 數(shù)據(jù)文件中的字段總數(shù)
- NR ? ? ? ? ? 已處理的輸入記錄數(shù)
- OFMT ? ? ? ? 數(shù)字的輸出格式,默認(rèn)值為%.6 g
- RLENGTH ? ? ?由match函數(shù)所匹配的子字符串的長(zhǎng)度
- RSTART ? ? ? 由match函數(shù)所匹配的子字符串的起始位置
核心解說(shuō):
在上面的列表中有一些 shell 腳本編程中的變量。 ARGC 和 ARGV 變量允許從 shell 中獲得命令行參數(shù)的總數(shù)以及它們的值。但這可能有點(diǎn)麻煩,因?yàn)間awk 并不會(huì)將程序腳本當(dāng)成命令行參數(shù)的一部分。
操作示例:
說(shuō)明:
?ARGC變量表明命令行上有兩個(gè)參數(shù)。這包括gawk命令和data1參數(shù)(記住,程序腳本并不算參數(shù))。ARGV數(shù)組從索引0開(kāi)始,代表的是命令。第一個(gè)數(shù)組值是gawk命令后的第一個(gè)命令行參數(shù)。
當(dāng)要在 gawk 程序中跟蹤數(shù)據(jù)字段和記錄時(shí),變量FNR 、 NF 和 NR 用起來(lái)就非常方便。有時(shí)并不知道記錄中到底有多少個(gè)數(shù)據(jù)字段。NF 變量可以讓你在不知道具體位置的情況下指定記錄中的最后一個(gè)數(shù)據(jù)字段。
操作示例:
NF 變量含有數(shù)據(jù)文件中最后一個(gè)數(shù)據(jù)字段的數(shù)字值??梢栽谒懊婕觽€(gè)美元符將其用作字段
變量。
FNR 和 NR 變量雖然類似,但又略有不同。 FNR 變量含有當(dāng)前數(shù)據(jù)文件中已處理過(guò)的記錄數(shù),
NR 變量則含有已處理過(guò)的記錄總數(shù)。下面的例子我們可以看到差別:
演示截圖:
?命令解說(shuō):
本例中g(shù)awk 程序的命令行定義了兩個(gè)輸入文件(兩次指定的是同樣的輸入文件)。 這個(gè)腳本會(huì)打印第一個(gè)數(shù)據(jù)字段的值和FNR 變量的當(dāng)前值。注意,當(dāng) gawk 程序處理第二個(gè)數(shù)據(jù)文件時(shí),F(xiàn)NR 值被設(shè)回了 1 。
演示截圖:?
?命令解說(shuō):
FNR 變量的值在 gawk 處理第二個(gè)數(shù)據(jù)文件時(shí)被重置了,而 NR 變量則在處理第二個(gè)數(shù)據(jù)文件時(shí) 繼續(xù)計(jì)數(shù)。結(jié)果就是:如果只使用一個(gè)數(shù)據(jù)文件作為輸入,F(xiàn)NR 和 NR 的值是相同的;如果使用多 個(gè)數(shù)據(jù)文件作為輸入,F(xiàn)NR 的值會(huì)在處理每個(gè)數(shù)據(jù)文件時(shí)被重置,而 NR 的值則會(huì)繼續(xù)計(jì)數(shù)直到處 理完所有的數(shù)據(jù)文件。
2.2 自定義變量
gawk 允許定義自己的變量在程序代碼中使用。 gawk 自定義變量名可以是任意數(shù)目的字母、數(shù)字和下劃線,但不能以數(shù)字開(kāi)頭。重要的是,要記住gawk 變量名區(qū)分大小寫(xiě)。
2.2.1 在腳本中給變量賦值
示例截圖:
命令說(shuō)明:
此示例中,a保存了前面賦予的值。
?截圖示例:
?命令說(shuō)明:
賦值語(yǔ)句還可以包含數(shù)學(xué)算式來(lái)處理數(shù)字值。
2.2.2. 在命令行上給變量賦值
gawk可以在 命令行來(lái)給程序中的變量賦值。允許在正常的代碼之外賦值,即時(shí)改變 變量的值。
演示截圖:
?說(shuō)明:
使用命令行參數(shù)來(lái)定義變量值會(huì)有一個(gè)問(wèn)題。在你設(shè)置了變量后,這個(gè)值在代碼的 BEGIN 部
分不可用。此時(shí)需要用到 -v參數(shù)來(lái)解決這個(gè)問(wèn)題。
操作示例:
?
本文摘自 :https://blog.51cto.com/u