【linux命令學習】— awk 命令學習

本人的CSDN博客地址
https://blog.csdn.net/u013332124/article/details/82974759

一、awk 介紹

awk是linux上一款強大的文本分析工具,它可以將文件逐行的讀入,然后用分割符分割開來,再對分割的各個部分進行處理。awk分割的各個部分叫做域,默認的分割符是空格和制表符??梢酝ㄟ^-F來指定分割符。

awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。

二、使用姿勢

主要語法

awk [參數(shù)] 'pattern{action}'

awk的使用看起來比較復(fù)雜,但是掌握好它的語法后,其實也很簡單。

和大多數(shù)的命令一樣,awk可以指定一些參數(shù),也可以不傳任何參數(shù)。awk具體支持哪些參數(shù)讀者可以通過man awk查看相關(guān)幫助文檔。這里就不多做介紹。

在參數(shù)后面跟著一個單引號括起來的執(zhí)行語句,其中pattern表示過濾規(guī)則,支持正則表達式和邏輯表達式。如果pattern涉及多個條件,可以用 &&|| 來關(guān)聯(lián),分別表示與和或。pattern可以不填,表示不過濾任何數(shù)據(jù)。

pattern后面根據(jù)一個花括號括起來的真正的執(zhí)行語句,比如 print $1 表示輸出分割后的第一個域。action{}可以有多個語句,以;號隔開。如果缺失action則表示輸出一整行的內(nèi)容。和{print}以及{print $0}效果一樣

使用示例

假設(shè)有一段文本test.txt,有2個用逗號隔開的列,分別表示姓名、年齡。

jack,18
nick,24
joe,19
hack,19

輸出所有人的名字

awk -F , '{print $1}' test.txt

-F ,表示用逗號作為分割符,之后pattern為空,action則為{print $1}。awk執(zhí)行后,每一行都會分割成兩列,之后輸出第一列的數(shù)據(jù)。其中1則表示第一列的數(shù)據(jù), \2則表示第二列的數(shù)據(jù),以此類推,$n則表示第n列的數(shù)據(jù)。要注意的是,$0表示的是這一整行的數(shù)據(jù)

輸出年齡小于20歲,并且名字中帶有ck內(nèi)容的人(整行正則匹配)

awk -F , '/ck/ && $2 < 20{print}' test.txt

上面用兩個斜杠//圍起來的就是正則表達式,awk會對每行進行正則匹配,匹配不上的就不會進行處理。

由于直接使用//匹配的是整行數(shù)據(jù),所以如果我們的需求是要找名字中帶有ck內(nèi)容的人的話,語句就不是很正確。因為如果這一行中剛好有其他字段也包含了ck,那么就可能造成誤匹配。那么,怎么就對名字這個字段進行正則匹配呢?

輸出年齡小于20歲,并且名字中帶有ck內(nèi)容的人(就對名字的字段進行匹配)

awk -F , '$1 ~ /ck/ && $2 < 20{print}' test.txt

$1 ~ //則表示對第一列數(shù)據(jù)進行正則匹配。

BEGIN和END關(guān)鍵字

action里面的語句會對每一行過濾后的數(shù)據(jù)進行輸出,那么,如果我們想在輸出的頭部和尾部增加一些內(nèi)容,應(yīng)該怎么做呢?答案就是使用BEGIN和END關(guān)鍵字。記得一定要大寫

BEGIN后面跟一個語句塊{},表示在awk掃描文本前輸出一些內(nèi)容。END用法也一樣,在awk掃描文本后輸出一些內(nèi)容。

awk -F , 'BEGIN {print "name,age"} {print} END {print "end"}' test.txt
//輸出 
name,age
jack,18
nick,24
joe,19
hack,19
end

上面的語句我們可以看到有3個{}語句塊,分別表示掃描前語句塊,掃描文本時使用的語句塊掃描后語句塊。

內(nèi)置變量

ARGC               命令行參數(shù)個數(shù)
ARGV               命令行參數(shù)排列
ENVIRON            支持隊列中系統(tǒng)環(huán)境變量的使用
FILENAME           awk瀏覽的文件名
FNR                瀏覽文件的記錄數(shù),也就是記錄所在的行數(shù)
FS                 設(shè)置輸入域分隔符,等價于命令行 -F選項
NF                 瀏覽記錄的域的個數(shù)
NR                 已讀的記錄數(shù)
OFS                輸出域分隔符
ORS                輸出記錄分隔符
RS                 控制記錄分隔符

awk內(nèi)置了一些變量,我們可以在語句塊直接使用 。

直接輸出第2行的數(shù)據(jù)

awk -F , 'FNR==2 {print}' test.txt

print和printf的區(qū)別

awk中同時提供了print和printf兩種打印輸出的函數(shù)。

其中print函數(shù)的參數(shù)可以是變量、數(shù)值或者字符串。字符串必須用雙引號引用括起來,參數(shù)必須用逗號分隔,不然多個參數(shù)之間連在一起會造成混淆。

printf和c語言中的printf基本一樣,可以格式化字符串。

print輸出例子

awk -F , '{print "name="$1",""age="$2}' test.txt

printf輸出例子

awk -F , '{printf "name=%s,age=%0.2f\n",$1,$2}' test.txt

//輸出
name=jack,age=18.00
name=nick,age=24.00
name=joe,age=19.00
name=hack,age=19.00

通過printf,我們可以將年齡轉(zhuǎn)化成小數(shù)點

三、awk 腳本

通過 -f scriptfile 來將awk執(zhí)行語句放到腳本中。我們可以編寫一個awk腳本test.awk。

BEGIN {print "name,age"}
$2 < 20 && /ck/ {print $1}
END {print "end"}

之后執(zhí)行

awk -F , -f test.awk test.txt

等同于執(zhí)行

awk -F , 'BEGIN {print "name,age"}  $2 < 20 && /ck/ {print $1} END {print "end"}'

awk腳本也可以這么寫

#!/usr/bin/awk -f
BEGIN {print "name,age"}
$2 < 20 && /ck/ {print $1}
END {print "end"}

之后直接執(zhí)行該腳本即可

./test.awk -F , test.txt

四、awk 編程

定義變量

awk語句中可以直接定義變量然后使用

# 設(shè)置count變量,統(tǒng)計一共有多少行
awk -F , '{count++;print $0} END {print count}' test.txt
# 設(shè)置count變量的初始值為1
awk -F , 'BEGIN{count=1} {count++;print $0} END {print count}' test.txt

我們可以在BEGIN語句塊中設(shè)置變量的初始值,如果print要輸出一個沒有定義過的變量,awk也不會報錯,而是輸出空字符串。

條件語句

awk的條件語句也和C語言基本一樣。

# 如果歲數(shù)小于20歲并且名字字段帶有ck,輸出的歲數(shù)就+5,否則就+1
awk -F , '{if($2<20 && $1 ~ /ck/){print $1,$2+5}else{print $1,$2+1}}' test.txt

上面的語句就是我們常見的if…else,很好理解。

循環(huán)語句

awk的循環(huán)語句也和C語言基本一樣。支持while、do/while、for、break、continue這些關(guān)鍵字。

# 每一行重復(fù)輸出3次
awk -F, 'BEGIN{i=0} {while(i<3){print $0;i++};i=0}' test.txt
awk -F, '{for(i=0;i<3;i++){print $0}}' test.txt

數(shù)組

awk的數(shù)組的下標可以是數(shù)字或者字母,這和js的map比較像。

# 輸出的過程中,遇到名字是nick的,把它的名字轉(zhuǎn)換成 hello 。最后我們再輸出一個world
awk -F, 'BEGIN{nickname["nick"]="hello";nickname[1]="world"} {if(nickname[$1]!=""){print nickname[$1],$2}else{print $1,$2}} END{print nickname[1]}' test.txt

上面的語句在BEGIN塊中定義了nickname的數(shù)組,同時使用了兩種下標,分別是"nick"和數(shù)字1。之后在后面也用到了。

五、寫在結(jié)尾

awk是linux上一款處理文本的神器,以前看到或者要用的時候總是習慣去百度,然后直接抄過來改一點東西,而沒有去較系統(tǒng)的學習一下。主要還是被它那看似復(fù)雜的語句塊嚇住,今天在認真看了幾篇awk教程后發(fā)現(xiàn)其本質(zhì)也很簡單,學習起來其實很快。個人覺的有編程基礎(chǔ)的人,差不多半個小時就足以將awk掌握個大概。

當然,要深入的學習awk肯定不是一件簡單的事,本篇博客也只是對awk的語句進行一些簡單的介紹,也足以應(yīng)付我們工作中大部分的需求。如果想深入學習awk的同學可以去官方文檔http://www.gnu.org/software/gawk/manual/gawk.html學習看看。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載 原文的排版和內(nèi)容都更加友好,并且詳細,我只是在這里貼出了一部分留作自己以后參考和學習,如希望更詳細了解AWK...
    XKirk閱讀 3,366評論 2 25
  • awk:報告生成器,格式化文本輸出 內(nèi)容: awk介紹 awk基本用法 awk變量 awk格式化 awk操作符 a...
    BossHuang閱讀 1,557評論 0 9
  • awk介紹awk變量printf命令:實現(xiàn)格式化輸出操作符awk patternawk actionawk數(shù)組aw...
    哈嘍別樣閱讀 1,738評論 0 4
  • awk: grep,sed,awk grep:文本過濾 sed:文本編輯 awk:文本格式化工具; 1 什么是aw...
    木林森閱讀 1,907評論 0 16
  • Linux指令中文說明傳送入口 整理自Linux指令中文說明 文本和數(shù)據(jù)進行處理的編程語言awk 是一種編程語言,...
    釋閑人閱讀 2,380評論 1 6

友情鏈接更多精彩內(nèi)容