溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

linux awk 一看就懂

發(fā)布時間:2020-08-07 17:40:02 來源:ITPUB博客 閱讀:116 作者:forest7707 欄目:建站服務(wù)器

linux awk 一看就懂
http://www.cnblogs.com/wangqiguo/p/5863266.html#_label12

awk是什么

awk是linux環(huán)境下的一個命令行工具,但是由于awk強大的能力,我們可以為awk工具傳遞一個字符串,該字符串的內(nèi)容類似一種編程語言的語法,我們可以稱其為Awk語言,而awk工具本身則可以看作是Awk語言的解析器。就好比python解析器與Python語言的關(guān)系。我們一般使用awk來做什么,awk又適合做什么工作呢。由于awk天生提供對文件中文本分列進行處理,所以如果一個文件中的每行都被特定的分隔符(常見的是空格)隔開,我們可以將這個文件看成是由很多列的文本組成,這樣的文件最適合用awk進行處理,其實awk在工作中很多時候被用來處理log文件,進行一些統(tǒng)計工作等。

awk命令的一般組成

awk最常用的工作一般是遍歷一個文件中的每一行,然后分別對文件的每一行進行處理,一個完整的awk命令形式如下:

awk  [options]  'BEGIN{ commands } pattern{ commands } END{ commands }'  file

其中options表示awk的可選的命令行選項,其中最常用的恐怕是 -F 它指定將文件中每一行分隔成列的分隔符號。而緊接著后面的單引號里面的所有內(nèi)容是awk的程序腳本,awk需要對文件每一行分割后的每一列做處理。file則是awk要處理的文件名稱。讓我們通過demo來體會awk的功能。

awk對每一行進行分割處理

echo '11 22 33 44' | awk '{print $3" "$2" "$1}'
輸出:33 22 11

我們將字符串 11 22 33 44 通過管道傳遞給awk命令,相當于awk處理一個文件,該文件的內(nèi)容就是 11 22 33 44 上面的命令中我們并沒有添加 -F 指定分割符號,實際上默認情況下awk使用空格分割每一行,如果需要指定別的字符則使用-F顯示指定。上面的命令是將 11 22 33 44 通過空格(不管列之間有多少個空格都將當作一個空格處理)分割成4列,在awk中有一種通過 $數(shù)字 引用的變量,這種變量引用的內(nèi)容就是當前行中分割的每一列的內(nèi)容,數(shù)字的序號從1開始,例如$1表示第1列的內(nèi)容,$2表示第二列,以此類推。$0 表示當前整行的內(nèi)容。print是awk的內(nèi)置函數(shù),用于打印出變量的值。 而我們在$3 $2 $1 之間添加了用雙引號引起來的空格,如果沒有,則這些變量的值打印出來會連在一起。這里的awk命令中{}里面的內(nèi)容實際上是我們上面完整模式的中間部分,我們省略了上面的BEGIN塊,END塊,并且中間的程序塊我們也省略掉了pattern部分,也就是如果不添加BEGIN或者END說明那么該程序塊就是上面完整模式中的中間的那個程序塊,該中間的程序塊所執(zhí)行的操作就是循環(huán)處理文件內(nèi)容的每一行,如果文件有10行,那么中間的程序塊要運行10次,每一次處理一行的內(nèi)容,并且處理完當前行之后,下次循環(huán)會自動依次處理接下來的行內(nèi)容。

我們來看看,如果有兩列是什么效果呢,例如:
    
echo -e '11 22 33 44\naa bb cc dd' | awk '{print $3" "$2" "$1}'
輸出:
33 22 11
cc bb aa

注意這里echo命令使用了-e選項的目的就是為了保持字符串中的\n的格式能夠生效,否則該換行將被忽略。那么上面的命令是如何執(zhí)行的呢,我們模擬一下awk的執(zhí)行過程,首先awk讀取第一行的內(nèi)容,使用空格分隔該行中的列,并將字符串11賦值給$1,22賦值給$2,33賦值給$3,44賦值給$4。然后通過print打印出來。接著讀取第二行的內(nèi)容,同樣執(zhí)行上面的操作。

使用parttern部分

我們已經(jīng)學(xué)習(xí)了awk最簡單的命令,下面我們再加一點東西進去,在程序塊的前面添加pattern部分,例如:

echo -e '1 2 3 4\n5 6 7 8' | awk '$1>2{print $3" "$2" "$1}'
輸出:7 6 5

該程序與上面的程序幾乎一樣,只不過我們在程序塊前面添加了  $1>2 表示如果當前行的第1列的值大于2則處理當前行,否則不處理。說白了pattern部分是用來從文件中篩選出需要處理的行進行處理的,如果沒有則循環(huán)處理文件中的所有行。pattern部分可以是任何條件表達式的判斷結(jié)果,例如>,<,==,>=,<=,!= 同時還可以使用+,-,*,/運算與條件表達式相結(jié)合的復(fù)合表達式,邏輯 &&,||,! 同樣也可以使用進來。另外pattern部分還可以使用 /正則/ 選擇需要處理的行。

awk的BEGIN語句塊

BEGIN語句塊是在匹配文件第一行之前運行的語句塊。由于是匹配第一行之前運行,實際上在BEGIN語句塊中 $n 是不可用的。一般情況下可以在BEGIN語句塊中做一些變量(awk中可以自定義變量,直接為一個變量賦值就定義了一個變量,awk中沒有專門定義變量的關(guān)鍵字)初始化的工作,以及一些只需要在開始僅打印一次的輸出信息(例如輸出表的表頭)。例如:

echo -e '1 2 3 4\n5 6 7 8' | awk 'BEGIN{print "c1 c2 c3";print ""}{print $3"  "$2"  "$1}'  
輸出為:
c1 c2 c3

3  2  1
7  6  5

注意一個語句塊(花括號包圍)中可以有多條語句,使用分號隔開,這與C語言一樣。如果需要單獨打印空行,需要使用 print "" 我們上面就實現(xiàn)了輸出表頭的效果。

awk的END語句塊

END語句塊是在awk循環(huán)執(zhí)行完所有行的處理之后,才執(zhí)行的,與BEGIN一樣,END語句塊也只執(zhí)行一次,我們看看完整的例子。

echo -e '1\n2\n3' | awk 'BEGIN{print "begin"}{print $1}END{print "end"}'
輸出:
begin
1
2
3
end

awk定義變量對列求和

test.txt 的內(nèi)容如下:
11 22 33
23 45 34
22 32 43

awk 'BEGIN{sum=0}{sum+=$1}END{print sum}' test.txt
輸出結(jié)果:56

首先在BEGIN語句塊中為變量sum賦值0,然后在循環(huán)語句塊中將每一行的第1列加到sum中,當文件的所有行全部循環(huán)處理完成之后,打印出sum變量的值。當然這個例子中BEGIN語句塊是可以省略的,我們可以直接在循環(huán)語句塊中使用sum變量,此時sum第一次使用,該變量會自動被建立,默認的初始值是0。

awk中的判斷語句

awk的所有語句塊中都可以使用判斷語句,其判斷語句語法與C語言一樣。

//test.txt內(nèi)容如下
1 2 3
4 5 6
7 8 9
10 11 12

awk '{if($1%2==0)print $1" "$2" "$3}' test.txt
輸出:
4 5 6
10 11 12

awk中的循環(huán)

//while循環(huán)
awk 'BEGIN{count=0;while(count<5){print count;count ++;}}'
輸出:
0
1
2
3
4
可以看出awk的一個語句塊中可以有比較復(fù)雜的復(fù)合語句,其使用與C語言幾乎差不多,多條語句之間用分號隔開,復(fù)合語句塊用花括號括起來做分隔。

//do..while循環(huán)
awk 'BEGIN{count=0;do{print count;count++}while(count<5)}'
輸出:
0
1
2
3
4

//for 循環(huán)
awk 'BEGIN{for(count=0;count<5;count++)print count}'
輸出:與上面一樣

可以看到這幾種循環(huán)的形式與C語言是一樣的,對于我們理解沒有任何障礙。awk中也使用break退出循環(huán),使用continue跳過本次循環(huán),其含義與C語言一樣。

使用數(shù)組分組求和,for..in循環(huán)

awk中的數(shù)組基本上可以看作是字典,看下面的例子:
//test.txt的文件內(nèi)容
zhangsan 2 3
lisi 5 6
zhangsan 8 9
lisi 11 12
wangwu 33 11

將所有第一列相同的分成一個組,并將該組中的第二列求和。
awk '{sum[$1]+=$2}END{for(k in sum)print k" "sum[k]}' test.txt
輸出:
zhangsan 10
lisi 16
wangwu 33
這個例子里面使用了for..in循環(huán)來遍歷數(shù)組的key,同時通過key來得到數(shù)組的值。對于key不是數(shù)字的數(shù)組,是不能通過普通的for循環(huán)來以數(shù)字索引訪問數(shù)組元素的。我們可以通過length()函數(shù)來獲得數(shù)組的元素個數(shù),例如length(array)

awk中的操作符與優(yōu)先級列表

linux awk 一看就懂

awk的內(nèi)置函數(shù)

awk定義了很多內(nèi)置函數(shù),下面我們根據(jù)函數(shù)類型列出常用的函數(shù),下面的函數(shù)只是一部分,完整的函數(shù)列表則需要查閱awk的官方文檔。

算術(shù):
atan2(y,x) 返回 y/x 的反正切。
cos(x) 返回 x 的余弦;x 是弧度。
sin(x) 返回 x 的正弦;x 是弧度。
exp(x) 返回 x 冪函數(shù)。
log(x) 返回 x 的自然對數(shù)。
sqrt(x) 返回 x 平方根。
int(x) 返回 x 的截斷至整數(shù)的值。
rand() 返回任意數(shù)字 n,其中 0 <= n < 1。
srand([expr]) 將 rand 函數(shù)的種子值設(shè)置為 Expr 參數(shù)的值,或如果省略 Expr 參數(shù)則使用某天的時間。返回先前的種子值。

字符串:
gsub(reg,str1,str2) 使用str1替換所有str2中符合正則表達式reg的子串
sub(reg,str1,str2) 含義與gsub相同,只不過gsub是替換所有匹配,sub只替換第一個匹配
index(str,substr) 返回substr在str中第一次出現(xiàn)的索引,注意索引從1開始計算,如果沒有則返回0
length(str) 返回str字符串的長度,length函數(shù)還可以返回數(shù)組元素的個數(shù)
blength(str) 返回字符串的字節(jié)數(shù)
match(str,reg) 與index函數(shù)一樣,只不過reg使用正則表達式,例如match("hello",/lo/)
split(str,array,reg)將str分隔成數(shù)組保存到array中,分隔使用正則reg,或者字符串都可以,返回數(shù)組長度
tolower(str) 轉(zhuǎn)換為小寫
toupper(str) 轉(zhuǎn)換為大寫
substr(str,start,length) 截取字符串,從start索引開始的length個字符,如不指定length則截取到末尾,索引從1開始

其他:
system(command) 執(zhí)行系統(tǒng)命令,返回退出碼
mktime( YYYY MM dd HH MM ss[ DST]) 生成時間格式
strftime(format,timestamp) 格式化時間輸出,將時間戳轉(zhuǎn)換為時間字符串
systime() 得到時間戳,返回從1970年1月1日開始到當前時間(不計閏年)的整秒數(shù)

awk的內(nèi)置變量

awk中同樣定義了很多內(nèi)置變量,我們可以直接像使用普通變量一樣使用他們,由于awk的版本眾多,有些內(nèi)置變量并不是得到所有awk版本的支持。

說明:[A][N][P][G]表示支持該變量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk
$n 當前記錄的第n個字段,比如n為1表示第一個字段,n為2表示第二個字段。
$0 這個變量包含執(zhí)行過程中當前行的文本內(nèi)容。
[N] ARGC 命令行參數(shù)的數(shù)目。
[G] ARGIND 命令行中當前文件的位置(從0開始算)。
[N] ARGV 包含命令行參數(shù)的數(shù)組。
[G] CONVFMT 數(shù)字轉(zhuǎn)換格式(默認值為%.6g)。
[P] ENVIRON 環(huán)境變量關(guān)聯(lián)數(shù)組。
[N] ERRNO 最后一個系統(tǒng)錯誤的描述。
[G] FIELDWIDTHS 字段寬度列表(用空格鍵分隔)。
[A] FILENAME 當前輸入文件的名。
[P] FNR 同NR,但相對于當前文件。
[A] FS 字段分隔符(默認是任何空格)。
[G] IGNORECASE 如果為真,則進行忽略大小寫的匹配。
[A] NF 表示字段數(shù),在執(zhí)行過程中對應(yīng)于當前的字段數(shù)。
[A] NR 表示記錄數(shù),在執(zhí)行過程中對應(yīng)于當前的行號。
[A] OFMT 數(shù)字的輸出格式(默認值是%.6g)。
[A] OFS 輸出字段分隔符(默認值是一個空格)。
[A] ORS 輸出記錄分隔符(默認值是一個換行符)。
[A] RS 記錄分隔符(默認是一個換行符)。
[N] RSTART 由match函數(shù)所匹配的字符串的第一個位置。
[N] RLENGTH 由match函數(shù)所匹配的字符串的長度。
[N] SUBSEP 數(shù)組下標分隔符(默認值是34)。

awk官方文檔:
https://www.gnu.org/software/gawk/manual/gawk.html

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI