1.命令簡(jiǎn)介
AWK 是文本處理語言,是一個(gè)強(qiáng)大的文本分析工具,是 Unix/Linux 環(huán)境中功能強(qiáng)大的數(shù)據(jù)處理引擎之一。數(shù)據(jù)可以來自標(biāo)準(zhǔn)輸入(stdin)、一個(gè)或多個(gè)文件或其它命令的輸出。它支持用戶自定義函數(shù)和動(dòng)態(tài)正則表達(dá)式等先進(jìn)功能,是 Unix/Linux 下一個(gè)強(qiáng)大的編程工具。
AWK 有很多內(nèi)建的功能,比如數(shù)組、函數(shù)等,這是它和 C 語言的相同之處,靈活性是 AWK 最大的優(yōu)勢(shì)。簡(jiǎn)單來說 AWK 就是把文件逐行的讀入,以空格和 Tab 為默認(rèn)分隔符將每行切片,切開的部分再進(jìn)行各種分析處理。
AWK 名稱來自于它的三位創(chuàng)始人 Alfred Aho、Peter Jay Weinberger 和 Brian Kernighan 姓氏的首個(gè)字母。AWK 有多個(gè)版本:awk, nawk, mawk 和 gawk,未作特別說明,一般指 gawk。gawk 是 AWK 的 GNU 版本。
2.命令格式
awk [OPTIONS]
awk [OPTIONS] ‘PATTERN{ACTION}’ FILE.。.
其中 PATTERN 一般為正則表達(dá)式,用斜杠括起來,用來查找匹配的行。ACTION 是在找到匹配的行時(shí)所執(zhí)行的一系列命令?;ɡㄌ?hào) {} 對(duì)一系列指令進(jìn)行功能分組,不需要始終出現(xiàn)。
盡管操作可能會(huì)很復(fù)雜,但語法總是這樣。awk 通常用來格式化文本文件中的信息,是以文件的行為處理單位,每接收文件的一行,然后執(zhí)行相應(yīng)的命令來處理文本。
注意:
(1)PATTERN 缺省為 1,表示永真,ACTION 缺省為 print。
(2)PATTERN + {ACTION} 可以同時(shí)存在多個(gè),每個(gè) PATTERN 之間的關(guān)系是或,只要當(dāng)前行匹配 PATTERN,則執(zhí)行 PATTERN 后大括號(hào)中的 action。
3.awk 的匹配模式
awk 的 PATTERN 可能是以下情況之一:
BEGIN
END
BEGINFILE
ENDFILE
/regular expression/
relational expression
pattern && pattern
pattern || pattern
! pattern
pattern ? pattern : pattern
(pattern)
pattern1, pattern2
BEGIN 和 END 是兩個(gè)特殊的模式,不會(huì)對(duì)輸入的內(nèi)容進(jìn)行測(cè)試。BEGIN 后的 action 在 awk 讀取文本前執(zhí)行,END 后的 action 在 awk 結(jié)束前執(zhí)行。模式表達(dá)式中的 BEGIN 和 END 模式不能與其他模式組合。
BEGINFILE 和 ENDFILE 是額外的兩個(gè)特殊模式,BEGINFILE 的 action 在讀取每個(gè)命令行輸入文件的第一條記錄之前執(zhí)行,ENDFILE 的 action 在讀取每個(gè)文件的最后一條記錄之后執(zhí)行。與 BEGIN 和 END 的區(qū)別是,如果給定多個(gè)文件,BEGINFILE 和 ENDFILE 的 action 將被執(zhí)行多次,而 BEGIN 和 END 不管是否給定文件,其 action 只會(huì)執(zhí)行一次。
/regular expression/ 表示正則表達(dá)式,用于選擇符合指定 pattern 的行。
relational expression 表示正則表達(dá)式的關(guān)系式,即多個(gè)正則表達(dá)式通過運(yùn)算符進(jìn)行組合。常見組合有:
pattern && pattern
邏輯與式,兩個(gè) pattern 同時(shí)滿足才算滿足
pattern || pattern
邏輯或式,只要有一個(gè) pattern 滿足即滿足
! pattern
邏輯非式,不符合 pattern 則為 true
pattern ? pattern : pattern
條件運(yùn)算符式,第一個(gè) pattern 滿足則判斷第二個(gè) pattern,否則判斷第三個(gè) pattern
(pattern)
括號(hào)用于改變 pattern 運(yùn)算的優(yōu)先級(jí)
pattern1, pattern2
表示一個(gè)范圍,用于選擇所有記錄行中第一個(gè)符合 pattern1 的記錄到下一個(gè)符合 pattern2 的記錄之間的記錄
4.選項(xiàng)說明
-C, --copyright
顯示版權(quán)信息并退出
-c, --traditional
是 awk 運(yùn)行在兼容模式下,gawk 的任何擴(kuò)展都不會(huì)生效
-d, --dump-variables[=FILE]
將 awk 排序后的全局變量的類型和值打印到指定的文件中,如果沒有指定 FILE,則在當(dāng)前目錄默認(rèn)生成一個(gè) awkvars.out
-E, --exec FILE
功能類似于選項(xiàng) -f,但腳本文件需要以 #! 開頭;另外命令行的變量將不再生效
-e, --source PROGRAM_TEXT
指定 awk 的源碼文件
-F, --field-separator FS
使用字符或字符串 FS 作為域分隔符。可以同時(shí)指定多個(gè)域分隔符,此時(shí)需要使用一對(duì)中括號(hào)括起來。例如使用-和|可寫作 -F ‘[-|]’。如果用[]作為分隔符,可寫作-F ‘[][]’。不指定分隔符,默認(rèn)為空格和 Tab。注意,使用 -F‘ ’顯示指定空格時(shí),Tab 也會(huì)被作為分隔符。使用 [] 指定多個(gè)分隔符時(shí),又想使多個(gè)分隔符組成的字符串也作為分隔符,在 [] 后添加一個(gè) +,如 -F“[ab]+”,那么分隔符有三個(gè),a,b 和 ab
-f, --file PROGRAM_FILE
從指定的 awk 腳本文件 PROGRAM_FILE 讀取 awk 指令
-g, --gen-pot
解析 awk 程序,產(chǎn)生 .po(Portable Object Template) 格式的文件到標(biāo)準(zhǔn)輸出,來標(biāo)明程序中每一個(gè)可本地化的字符串位置
-h, --help
顯示簡(jiǎn)要的幫助信息并退出
-L, --lint[=VALUE]
打印有關(guān)在其它版本 awk 中出現(xiàn)可疑的或不可移植結(jié)構(gòu)的警告。該選項(xiàng)提供了一個(gè)可選的參數(shù) fatal,即將警告視為致命的錯(cuò)誤
-m{f|r} VAL
-mf 將最大字段數(shù)設(shè)為 VAL;-mr 將最大記錄數(shù)設(shè)為 VAL。這兩個(gè)功能是 Bell 實(shí)驗(yàn)室版awk 的擴(kuò)展功能,在標(biāo)準(zhǔn) awk 中不適用
-N, --use-lc-numeric
使用本地小數(shù)點(diǎn)解析輸入的數(shù)據(jù)
-n, --non-decimal-data
識(shí)別輸入數(shù)據(jù)中八進(jìn)制和十六進(jìn)制數(shù)
-O, --optimize
在程序的內(nèi)部表示上啟用優(yōu)化。目前,這只包括簡(jiǎn)單的常量折疊。gawk 維護(hù)者希望隨著時(shí)間的推移增加額外的優(yōu)化
-P, --posix
打開兼容模式,會(huì)出現(xiàn)以下限制:
不識(shí)別 x;
當(dāng)域分隔符 FS 是一個(gè)空格時(shí),只有空格和 Tab 能作為域分隔符,換行符將不能作為一個(gè)域分隔符;
在 ? 和 : 之后,不能繼續(xù)當(dāng)前行;
函數(shù)關(guān)鍵字 func 將不能被識(shí)別;
操作符 ** 和 **= 不能代替 ^ 和 ^=;
fflush 函數(shù)無效。
-R, --command FILE
只限于 Dgawk。從文件中讀取調(diào)試器命令
-r, --re-interval
允許間隔正則表達(dá)式的使用。為默認(rèn)選項(xiàng)
-S, --sandbox
在沙盒模式下運(yùn)行g(shù)awk,禁用 system() 函數(shù),使用 getline 進(jìn)行輸入重定向,使用 print 和 printf 進(jìn)行輸出重定向,以及加載動(dòng)態(tài)擴(kuò)展。命令執(zhí)行也被禁用,這有效地阻止了腳本訪問本地資源
-t, --lint-old
打印關(guān)于不能向傳統(tǒng) Unix awk 移植的構(gòu)造的警告
--profile[=FILE]
輸出性能分析報(bào)告至指定的文件,默認(rèn)輸出到 awkprof.out
-V, --version
打印版本信息并退出
-v, --assign VAR=VAL
定義一個(gè) awk 變量并賦值,可以將外部變量傳遞給 awk
--
標(biāo)識(shí)命令選項(xiàng)結(jié)束
5.awk 調(diào)用方式
有三種方式調(diào)用 awk。
(1)命令行方式。
awk [-F FS] ‘PATTERN + {ACTION}’ FILE.。.
在 awk 中,文件的每一行中,由域分隔符分開的每一項(xiàng)稱為一個(gè)域。通常,在不指明域分隔符的情況下,默認(rèn)為空格和 Tab。
(2)Shell 腳本方式。
將所有的 awk 命令插入一個(gè)文件,腳本中在首行注明使用 awk 命令來解析執(zhí)行,相當(dāng)于將 Shell 腳本首行的#!/bin/sh換成#!/bin/awk,最后通過鍵入腳本名稱來調(diào)用。
(3)將所有的 awk 命令插入到一個(gè)單獨(dú)文件,然后使用 -f 選項(xiàng)調(diào)用。
awk -f awk-script-file FILE.。.
其中,-f 選項(xiàng)加載 awk-script-file 中的 awk 腳本,F(xiàn)ILE… 跟上面的是一樣的。
6.awk 內(nèi)置變量
gawk 有許多內(nèi)置變量用來設(shè)置環(huán)境信息,這些變量可以被改變,下面給出常見的內(nèi)置變量說明。
$0 當(dāng)前處理行
$n 當(dāng)前記錄的第 n 個(gè)字段,n 從 1 開始,字段間由 FS 分隔
ARGC 命令行參數(shù)個(gè)數(shù)
ARGIND 當(dāng)前處理命令行中的第幾個(gè)文件,文件下標(biāo)從 0 開始
ARGV 命令行參數(shù)數(shù)組
CONVFMT 數(shù)字轉(zhuǎn)換格式,默認(rèn)值為%.6g
ENVIRON 支持隊(duì)列中系統(tǒng)環(huán)境變量的使用
ERRNO 最后一個(gè)系統(tǒng)錯(cuò)誤的描述
FIELDWIDTHS 字段寬度列表(用空格鍵分隔)
FILENAME awk瀏覽的文件名
FNR 當(dāng)前被處理文件的記錄數(shù)
FS 設(shè)置輸入域分隔符,等價(jià)于命令行-F選項(xiàng)
IGNORECASE 如果為真,則進(jìn)行忽略大小寫的匹配
LINT 動(dòng)態(tài)控制--lint選項(xiàng)是否生效,為false不生效,為true則生效;
NF 瀏覽記錄的域的個(gè)數(shù)
NR 已讀的記錄數(shù)
OFMT 數(shù)字的輸出格式,默認(rèn)值是%.6g
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS The input record separator,輸入記錄的分隔符,默認(rèn)為換行符
RT The record terminator,輸入記錄的結(jié)束符
RSTART 由 match 函數(shù)所匹配的字符串的第一個(gè)位置
RLENGTH 由 match 函數(shù)所匹配的字符串的長(zhǎng)度
SUBSEP 數(shù)組下標(biāo)分隔符(默認(rèn)值是 34)
TEXTDOMAIN awk 程序所使用的文本所處的地域
7.awk 編程示例
7.1 基礎(chǔ)打印輸出
(1)假設(shè) last -n 5 的輸出如下:
root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in
root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)
dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)
root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
如果只是顯示最近登錄的5個(gè)帳號(hào):
last -n 5 | awk ‘{print $1}’
root
root
root
dmtsai
root
awk 工作流程是這樣的:讀入有換行符分隔的一條記錄,然后將記錄按指定的域分隔符劃分,$0則表示所有域,$1表示第一個(gè)域,$n表示第 n 個(gè)域。默認(rèn)域分隔符是空格或 Tab 符,所以$1表示登錄用戶,$3表示登錄用戶 ip,以此類推。
(2)如果想顯示 /etc/passwd 配置文件中的賬戶以及賬戶對(duì)應(yīng)的 Shell,而賬戶與 Shell 之間以Tab符分隔。
cat /etc/passwd |awk -F ‘:’ ‘{print $1“ ”$7}’
root /bin/bash
daemon /bin/sh
bin /bin/sh
sys /bin/sh
注意,這里使用了 -F 指定域分隔符為冒號(hào) :。
(3)如果只是顯示 /etc/passwd 的賬戶和賬戶對(duì)應(yīng)的 Shell,而賬戶與 Shell 之間以逗號(hào)分隔,而且在所有行添加列名 name,shell,在最后一行添加 blue,/bin/nosh。
cat /etc/passwd |awk -F ‘:’ ‘BEGIN {print “name,shell”} {print $1“,”$7} END {print “blue,/bin/nosh”}’
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
。..。
blue,/bin/nosh
awk 工作流程是這樣的:先執(zhí)行 BEGING,然后讀取文件,讀入有/n換行符分割的一條記錄,然后將記錄按指定的域分隔符劃分域,填充域,$0則表示所有域,$1表示第一個(gè)域,$n表示第 n 個(gè)域,隨后開始執(zhí)行模式所對(duì)應(yīng)的動(dòng)作action。接著開始讀入第二條記錄······直到所有的記錄都讀完,最后執(zhí)行END操作。
(4)搜索 /etc/passwd 有 root 關(guān)鍵字的所有行。
awk -F: ‘/root/’ /etc/passwd
root0root:/root:/bin/bash
上面三種是 awk 的 action 的使用示例,而這種是 pattern 的使用示例,匹配了 pattern(這里是root)的行才會(huì)執(zhí)行 action(沒有指定 action,默認(rèn)輸出每行的內(nèi)容)。
搜索支持正則表達(dá)式,例如找 root 開頭的所有行。
awk -F: ‘/^root/’ /etc/passwd
(5)搜索/etc/passwd有 root 關(guān)鍵字的所有行,并顯示對(duì)應(yīng)的 Shell。
awk -F: ‘/root/{print $7}’ /etc/passwd
/bin/bash
這里是 awk 的 pattern+action 示例用法,同時(shí)指明了 action 是 {print $7}。
(6)打印 /etc/passwd 第三行的第一列和第二列。
awk -F: ‘NR==3{print $1,$2;}’ /etc/passwd
#輸出結(jié)果:
daemon x
7.2 awk 在每一列后添加字符串后輸出
設(shè)定變量?jī)?nèi)容:
a=“/test.html /dir1 /abc.txt”
希望得到
echo $a
--exclude=/test.html --exclude=/dir1 --exclude=/abc.txt
如何用 awk 實(shí)現(xiàn)。
解決辦法:
echo $a|awk ‘{for(i=1;i《=NF-1;++i){printf “-execute=%s ”,$i}}{print “--exclude=”$NF“”}’
#或者
echo $a|awk ‘{for(i=1;i《=NF;i++){printf “--exclude=”$i“ ”}{print “”}}’
后者是網(wǎng)友給出的答案,和我上面的寫法差不多,只是對(duì) printf 在使用形式上有所差別而已。第二種方法print “”用于換行,print 每次輸出后默認(rèn)進(jìn)行換行。
7.3 Shell 編程使用 awk 浮點(diǎn)運(yùn)算保留兩位小數(shù)
a=3
b=10
c=$(awk ‘BEGIN{printf “%.2f”,’$a‘*100/’$b‘}’)
echo c:$c%
或者:
c=$(awk -v n=$a -v m=$b ‘BEGIN{printf “%.2f”,n*100/m}’)
echo c:$c%
-v表示定義awk的變量!v是variable的首字母。輸出:c:30.00%。
7.4 awk 訪問 Shell 變量
awk 默認(rèn)是無法訪問shell變量的,我所知道的有三種方法。
方法一:awk -v 選項(xiàng)讓awk 里使用shell變量。
var0=dablelv0
var1=dablelv1
awk -v tmpVar0=$var0 -v tmpVar1=$var1 ‘BEGIN{print tmpVar0“ ”tmpVar1}’
輸出:dablelv0 dablelv1
注意:BEGIN 必須大寫,awk 的 {action} 必須要使用單引號(hào)括起來。
方法二:‘“$var”’
這種寫法是老外常用的寫法。如:
var=“test”
awk ‘BEGIN{print “’$var‘”}’
這種寫法其實(shí)際是雙括號(hào)變?yōu)閱卫ㄌ?hào)的常量,傳遞給了awk。
如果var中含空格,為了shell不把空格作為分格符,應(yīng)該如下使用:
var=“this is a test”
awk ‘BEGIN{print “’”$var“‘”}’
方法三:export 變量,將變量設(shè)置為臨時(shí)會(huì)話環(huán)境變量,僅在當(dāng)前shell會(huì)話中有效。在awk中使用ENVIRON[“var”]形式訪問變量。
var=“this is a test”
export $var #或者 export var
#或者
export var=“this is a test”
awk ‘BEGIN{print ENVIRON[“var”]}’
7.5 awk 執(zhí)行 Shell 命令
awk 執(zhí)行 Shell 命令有兩種方法。
方法一:使用awk的system()函數(shù)。
export var=dablelv
awk ‘BEGIN{system(“echo $var”)}’
輸出:dablelv
注意:一定要使用export將變量設(shè)置為臨時(shí)環(huán)境變量,因?yàn)閍wk的system()實(shí)際上是新建了一個(gè)shell進(jìn)程來執(zhí)行給定的shell命令,否則無法訪問父進(jìn)程的變量。
方法二:使用使用print cmd | “/bin/bash”
var=“this is a test”
awk ‘BEGIN{print “echo ”“’”$var“‘”|“sh”}’
#或者
var=“this is a test”
awk -v varTmp=“$var” ‘BEGIN{print “echo ”varTmp|“sh”}’
輸出:
this is a test
注意:
(1)指定bash的時(shí)候需要雙引號(hào)括起來;
(2)方法二與方法一的區(qū)別在于方法二是將變量在awk解析后再通過管道傳給shell,所以無需將變量設(shè)置為臨時(shí)環(huán)境變量,因?yàn)閟hell接收到的變量已經(jīng)是變量的值。
8.awk 常見問題
(1)awk 默認(rèn)以空格和 Tab 作為域分隔符,現(xiàn)在只以空格為分隔符,需要使用中括號(hào)的方式,不使用中括號(hào),則仍然會(huì)將 Tab 作為域分隔符。
# 錯(cuò)誤的寫法
awk -F‘ ’ ‘{print $1;}’ test.txt
# 正確的寫法
awk -F‘[ ]’ ‘{print $1;}’ test.txt
原文標(biāo)題:每天一個(gè) Linux 命令(132):awk 命令
文章出處:【微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
責(zé)任編輯:haq
-
Linux
+關(guān)注
關(guān)注
87文章
11332瀏覽量
210023
原文標(biāo)題:每天一個(gè) Linux 命令(132):awk 命令
文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論