日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

詳解著名的awk oneliner,第一部分:空行、行號(hào)和計(jì)算

 王少斌 2011-07-12

將每行后面都添加一個(gè)空行

awk '1; { print "" }'

這是怎么意思呢?一個(gè)單行awk命令,其實(shí)也是一個(gè)用awk語(yǔ)言寫的程序,每個(gè)awk程序,都是由一系列的“匹配模式 { 執(zhí)行動(dòng)作 }”語(yǔ)句所組成的。在這個(gè)例子里面,有兩個(gè)語(yǔ)句,“1”和“{print ""}”。在每個(gè)“匹配模式——執(zhí)行動(dòng)作”語(yǔ)句中,模式和動(dòng)作都是可以被省略的。如果匹配模式被省略,那么預(yù)定的動(dòng)作將會(huì)對(duì)輸入文件的每一行執(zhí)行。如果動(dòng) 作被省略,那么就默認(rèn)會(huì)執(zhí)行{print }。所以,這個(gè)單行awk語(yǔ)句等同于下面的語(yǔ)句

awk '1 {print } {print ""}'

動(dòng)作只有在匹配模式的值為真的時(shí)候才會(huì)執(zhí)行。因?yàn)?#8220;1”永遠(yuǎn)為真,所以,這個(gè)例子也可以寫成下面的形式

awk '{print } {print ""}'

awk中每條print語(yǔ)句后都默認(rèn)會(huì)輸出一個(gè)ORS變量(Output Record Separator,即輸出行分隔符,默認(rèn)為換行符)。第一個(gè)不帶參數(shù)的print語(yǔ)句,等同于print $0,其中$0是代表整行內(nèi)容的變量。第二個(gè)print語(yǔ)句什么也不輸出,但是鑒于print語(yǔ)句后都會(huì)被自動(dòng)加上ORS變量,這句的作用就是輸出一個(gè)新行。于是每行后面加空行的目的就達(dá)到了。

添加空行的另一種方法

awk 'BEGIN { ORS="\n\n" }; 1'

BEGIN是一個(gè)特殊的模式,后面所接的內(nèi)容,會(huì)在文件被讀入前執(zhí)行。這里,對(duì)ORS變量進(jìn)行了重新定義,將一個(gè)換行符改成了兩個(gè)。后面的“1”,同樣等價(jià)于{print },這樣就達(dá)到了在每行后用新的ORS添加空行的目的。

在每個(gè)非空的行后面添加空行

awk 'NF {print $0 "\n"}'

這個(gè)語(yǔ)句里面用到了一個(gè)新的變量,NF(number of fields),即本行被分割成的字段的數(shù)目。例如,“this is a test”,會(huì)被awk分割成4個(gè)詞語(yǔ),NF的值就為4。當(dāng)遇到空行,分割后的字段數(shù)為0,NF為0,后面的匹配動(dòng)作就不會(huì)被執(zhí)行。這條語(yǔ)句,可以理解成 “如果這一行可以分割成任意大于0的部分,那么輸出當(dāng)前行以及一個(gè)換行符”。

在每行后添加兩個(gè)空行

awk '1; {print "\n"}'

這一語(yǔ)句與前面的很相似。“1”可以理解為{print },所以整個(gè)句子可以改寫為

awk '{print ; print "\n"}'

它首先輸出當(dāng)前行,然后再輸出一個(gè)換行符以及一個(gè)結(jié)束print語(yǔ)句的ORS,也就是另外一個(gè)換行符。

為每個(gè)文件的內(nèi)容添加行號(hào)

awk '{ print FNR "\t" $0 }'

這個(gè)awk程序在每行的內(nèi)容前添加了一個(gè)變量FNR的輸出,并用一個(gè)制表符進(jìn)行分隔。FNR(File Number of Row)這個(gè)變量記錄了當(dāng)前行在當(dāng)前文件中的行數(shù)。在處理下一個(gè)文件時(shí),這個(gè)變量會(huì)被重置為0。

為所有文件的所有行統(tǒng)一添加行號(hào)

awk '{print NR "\t" $0}'

這一句與上一例基本一樣,除了使用的行號(hào)變量是NR(Number of Row),這個(gè)變量不會(huì)在處理新文件的時(shí)候被重置。所以說,如果你有2個(gè)文件,一個(gè)10行一個(gè)12行,那這個(gè)變量會(huì)從1一直變到22。

用更漂亮的樣式添加行號(hào)

awk '{printf("%5d : %s\n", FNR, $0)}'

這個(gè)例子用了printf函數(shù)來自定義輸出樣式,它所接受的參數(shù)與標(biāo)準(zhǔn)C語(yǔ)言的printf函數(shù)基本一致。需要注意的是,printf后不會(huì)被自動(dòng)添加ORS,所以你需要自己指定換行。這個(gè)語(yǔ)句指定了行號(hào)會(huì)右對(duì)齊,然后是一個(gè)空格和冒號(hào),接著是當(dāng)前行的內(nèi)容。

為文件中的非空行添加行號(hào)

awk 'NF { $0=++a " :" $0}; {print }'

Awk的變量都是自動(dòng)定義的:你第一次用到某個(gè)變量的時(shí)候它就自動(dòng)被定義了。這個(gè)語(yǔ)句在每次遇到一個(gè)非空行的時(shí)候先把一個(gè)變量a加1,然后把a(bǔ)的數(shù)值添加到行首,然后輸出當(dāng)前行的內(nèi)容。

計(jì)算文件行數(shù)(模擬 wc -l)

awk 'END {print NR}'

END是另外一個(gè)不會(huì)被檢驗(yàn)是否為真的模式,后面的動(dòng)作會(huì)在整個(gè)文件被讀完后進(jìn)行。這里是輸出最終的行號(hào),即文件的總行數(shù)。

對(duì)每行求和

awk '{s=0;for (i=0;i<NF;i++) s=s+$i; print s}'

Awk有些類似C語(yǔ)言的語(yǔ)法,比如這里的for (;;;){ ... }循環(huán)。這句命令會(huì)讓程序遍歷所有NF個(gè)字段,并把字段的總和存在變量s中,最后輸出s的數(shù)值并處理下一行。

對(duì)所有行所有字段求和

awk '{for (i=0;i<NF;i++) s=s+$i; END {print s+0}'

這個(gè)例子與上一個(gè)基本一致,除了輸出的是所有行所有字段的和。由于變量會(huì)被自動(dòng)定義,s只需要定義一次,故而不需要把s定義成0。另外需要注意的是,它輸出{print s+0}而非{print s},這是因?yàn)槿绻募榭眨瑂不會(huì)被定義就不會(huì)有任何輸出了,輸出s+0可以保證在這種情況下也會(huì)輸出更有意義的0。

將所有字段替換為其絕對(duì)值

awk '{ for (i = 1; i <= NF; i++) if ($i < 0) $i = -$i; print }'

這條語(yǔ)句用了C語(yǔ)言的另外兩個(gè)特性,一個(gè)是if (...) {...}結(jié)構(gòu),另外就是省略了大括號(hào)。它檢查對(duì)每一行,檢查每個(gè)字段的值是否小于0,如果值小于0,則將其改為正數(shù)。字段名可以間接地用變量的形式引用,如i=5;$i='hello'會(huì)將第5個(gè)字段的內(nèi)容置為hello。

下面的是將這條語(yǔ)句完整的寫出來的形式。print語(yǔ)句會(huì)在行中所有字段被改為正數(shù)后執(zhí)行。

awk '{
for (i = 1; i <= NF; i++) {
if ($i < 0) {
$i = -$i;
}
}
print
}'

計(jì)算文件中的總字段(單詞)數(shù)

awk '{total=total+NF};END {print total+0}'

這個(gè)命令匹配所有的行,并不斷的把行中的字段數(shù)累加到變量total。執(zhí)行完成上述動(dòng)作后,輸出total的數(shù)值。

輸出含有單詞Beth的行的數(shù)目

awk '/Beth/ {n++}; END {print n+0}'

這個(gè)例子含有兩個(gè)語(yǔ)句。第一句找出匹配/Beth/的行,并對(duì)變量n進(jìn)行累加。在/.../之間的內(nèi)容為正則表達(dá)式,/Beth/匹配所有含有 “Beth”的單詞(它不僅匹配Beth,同樣也匹配Bethe)。第二句在文件處理完成后輸出n的數(shù)值。這里用n+0是為了讓n為0 的情況下輸出0而不是一個(gè)空行。

尋找第一個(gè)字段為數(shù)字且最大的行

awk '$1 > max { max=$1; maxline=$0 }; END { print max, maxline }'

這個(gè)例子用變量max記錄第一個(gè)字段的最大值,并把第一個(gè)字段最大的行的內(nèi)容存在變量maxline中。在循環(huán)終止后,輸出max和maxline的內(nèi)容。注意:如果在數(shù)字都為負(fù)數(shù)的情況下,這個(gè)例子就不能用了,下面的是修改過的版本

awk 'NR == 1 { max = $1; maxline = $0; next; } $1 > max { max=$1; maxline=$0 }; END { print max, maxline }'

在每一行前添加輸出該行的字段數(shù)

awk '{print NF ":" $0}'

這個(gè)例子僅僅是在逐行輸出字段數(shù)NF,一個(gè)冒號(hào),以及該行的內(nèi)容。

輸出每行的最后一個(gè)字段

awk '{print $NF}'

awk里面的字段可以用變量的形式引用。這一句輸出第NF個(gè)字段的內(nèi)容,而NF就是該行的字段數(shù)。

打印最后一行的最后一個(gè)字段

awk '{ field = $NF };END {print field}'

這個(gè)例子用field記錄最后一個(gè)字段的內(nèi)容,并在循環(huán)后輸出field的內(nèi)容。

這里是一個(gè)更好的版本。它更常用、更簡(jiǎn)潔也更高效:

awk 'END {print $NF}'

輸出所有字段數(shù)大于4的行

awk 'NF > 4'

這個(gè)例子省略了要執(zhí)行的動(dòng)作。如前所述,省略動(dòng)作等價(jià)于{print}。

輸出所有最后一個(gè)字段大于4的行

awk '$NF > 4'

這個(gè)例子用$NF引用最后一個(gè)字段,如果它的數(shù)值大于4,那么就輸出。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多