日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux命令终极系列awk

發布時間:2024/7/23 linux 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux命令终极系列awk 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


AWK man 手冊:http://man.linuxde.net/awk

AWK編程的內容極多,這里只羅列簡單常用的用法,更多請參考?http://www.gnu.org/software/gawk/manual/gawk.html


簡介

什么是awk??

? ? ? ? awk是一個強大的文本分析工具,相對于grep的查找,sed的編輯,awk在其對數據分析并生成報告時,顯得尤為強大。簡單來說,awk就是把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。即awk處理過程: 依次對每一行進行處理,然后輸出。

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

? ? ? ? awk其名稱得自于它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。正是這三個人創造了awk---一個優秀的樣式掃描與處理工具。實際上 AWK 的確擁有自己的語言: AWK 程序設計語言, 三位創建者已將它正式定義為“樣式掃描和處理語言”。?它允許您創建簡短的程序,這些程序讀取輸入文件、為數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。


AWK的功能是什么?

? ? ? ? 與sed和grep很相似,awk是一種樣式掃描與處理工具。但其功能卻大大強于sed和grep。awk提供了極其強大的功能:它幾乎可以完成grep和sed所能完成的全部工作,同時,它還可以可以進行樣式裝入、流控制、數學運算符、進程控制語句甚至于內置的變量和函數。它具備了一個完整的語言所應具有的幾乎所有精美特性。實際上,awk的確擁有自己的語言:awk程序設計語言,awk的三位創建者已將它正式定義為:樣式掃描和處理語言。

為什么使用awk?

? ? ? ? 使用awk的第一個理由是基于文本的樣式掃描和處理是我們經常做的工作,awk所做的工作有些象數據庫,但與數據庫不同的是,它處理的是文本文件,這些文件沒有專門的存儲格式,普通的人們就能編輯、閱讀、理解和處理它們。而數據庫文件往往具有特殊的存儲格式,這使得它們必須用數據庫處理程序來處理它們。既然這種類似于數據庫的處理工作我們經常會遇到,我們就應當找到處理它們的簡便易行的方法,UNIX有很多這方面的工具,例如sed 、grep、sort以及find等等,awk是其中十分優秀的一種。?

? ? ? ? 使用awk的第二個理由是awk是一個簡單的工具,當然這是相對于其強大的功能來說的。的確,UNIX有許多優秀的工具,例如UNIX天然的開發工具C語言及其延續C++就非常的優秀。但相對于它們來說,awk完成同樣的功能要方便和簡捷得多。這首先是因為awk提供了適應多種需要的解決方案:從解決簡單問題的awk命令行到復雜而精巧的awk程序設計語言,這樣做的好處是,你可以不必用復雜的方法去解決本來很簡單的問題。例如,你可以用一個命令行解決簡單的問題,而C不行,即使一個再簡單的程序,C語言也必須經過編寫、編譯的全過程。其次,awk本身是解釋執行的,這就使得awk程序不必經過編譯的過程,同時,這也使得它與shell script程序能夠很好的契合。最后,awk本身較C語言簡單,雖然awk吸收了C語言很多優秀的成分,熟悉C語言會對學習awk有很大的幫助,但awk本身不須要會使用C語言――一種功能強大但需要大量時間學習才能掌握其技巧的開發工具。
基于以上理由,再加上awk強大的功能,我們有理由說,如果你要處理與文本樣式掃描相關的工作,awk應該是你的第一選擇。在這里有一個可遵循的一般原則:如果你用普通的shell工具或shell script有困難的話,試試awk,如果awk仍不能解決問題,則便用C語言,如果C語言仍然失敗,則移至C++。?

AWK調用方式

有三種方式調用awk

1.AWK命令行方式 awk [-F field-separator] 'commands' input-file(s) 其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。 在awk中,文件的每一行中,由域分隔符分開的每一項稱為一個域。通常,在不指名-F域分隔符的情況下,默認的域分隔符是空格。 2.shell腳本方式 將一段awk程序寫入文本文件,然后在它的第一行加上: #!/bin/awk -f 并賦予這個文本文件以執行的權限。$awk腳本文本名 待處理文件 3.使用-f選項調用awk程序。awk允許將一段awk程序寫入一個文本文件,然后在awk命令行中用-f選項調用并執行這段程序。 awk -f awk-script-file input-file(s) 其中,-f選項加載awk-script-file中的awk腳本,input-file(s)跟上面的是一樣的。

AWK語法

基本語法 awk [opion] 'awk_script' input_file1 [input_file2 ...] awk的常用選項option有:-F fs : 使用fs作為輸入記錄的字段分隔符,如果省略該選項,awk使用環境變量IFS的值-f filename : 從文件filename中讀取awk_script-v var=value : 為awk_script設置變量awk '{pattern + action}' {filenames} awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file [-F|-f|-v] 大參數,-F指定分隔符,-f調用腳本,-v定義變量 var=value ' ' 引用代碼塊 BEGIN 初始化代碼塊,在對每一行進行處理之前,初始化代碼,主要是引用全局變量,設置FS分隔符 // 匹配代碼塊,可以是字符串或正則表達式 {} 命令代碼塊,包含一條或多條命令 ; 多條命令使用分號分隔 END 結尾代碼塊,在對每一行進行處理之后再執行的代碼塊,主要是進行最終計算或輸出結尾摘要信息 file awk的輸入文件,可以有多個。注意:awk不會修改輸入文件。如果沒有指定輸入文件,那么默認為標準輸入(屏幕)

awk的變量

awk提供兩種變量:
(1) 內置變量
  在引用時,不需要加$
(2) 自定義變量
? ? ? ? awk中引用自定義變量必須在它前面加上標志符"$"。awk根據其在awk中第一次出現的形式和上下文確定其具體的數據類型。當變量類型不確定時,awk默認其為字符串類型。這里有一個技巧:如果你要讓你的awk程序知道你所使用的變量的明確類型,你應當在在程序中給它賦初值。

awk的記錄,字段與內置變量
 1. 記錄與字段
在 awk中,缺省的情況下總是將文本文件中的一行視為一個記錄,而將一行中的某一部分作為記錄中的一個字段。為了操作這些不同的字段,awk借用shell 的方法,用$1,$2,$3...這樣的方式來順序地表示行(記錄)中的不同字段。特殊地,awk用$0表示整個行(記錄)。不同的字段之間是用稱作分隔 符的字符分隔開的。系統默認的分隔符是空格。awk允許在命令行中用-F re的形式來改變這個分隔符。事實上,awk用一個內置的變量FS來記憶這個分隔符
? 2. 內置變量
  
awk中有好幾個這樣的內置變量,例如,記錄分隔符變量RS、當前工作的記錄數NR等等。
? 示例:顯示文件本文件testAwk中第3行到第6行,以字符%分隔的第一個字段,第三個字段:
 awk -F % 'NR==3,NR==6 {printf $1? $3}' testAwk
???
? 示例:殺死系統中所有top進程
????ps -ef|grep " top" |grep -v "grep"|awk '{printf $2}'|xargs kill -9
??? 或
????kill -9 `ps -ef|grep " top" |grep -v "grep"|awk '{printf $2}'`


$0 表示整個當前行 $1 每行第一個字段 NF 字段數量變量 NR 每行的記錄號,多文件記錄遞增 FNR 與NR類似,不過多文件記錄不遞增,每個文件都從1開始 \t 制表符 \n 換行符 FS BEGIN時定義分隔符 RS 輸入的記錄分隔符, 默認為換行符(即文本是按一行一行輸入) ~ 匹配,與==相比不是精確比較 !~ 不匹配,不精確比較 == 等于,必須全部相等,精確比較 != 不等于,精確比較 &&  邏輯與 || 邏輯或 + 匹配時表示1個或1個以上 /[0-9][0-9]+/ 兩個或兩個以上數字 /[0-9][0-9]*/ 一個或一個以上數字 FILENAME 文件名 OFS 輸出字段分隔符, 默認也是空格,可以改為制表符等 ORS 輸出的記錄分隔符,默認為換行符,即處理結果也是一行一行輸出到屏幕 -F'[:#/]' 定義三個分隔符

awk內置變量

awk有許多內置變量用來設置環境信息,這些變量可以被改變,下面給出了最常用的一些變量。

ARGC 命令行參數個數 ARGV 命令行參數排列 ENVIRON 支持隊列中系統環境變量的使用 FILENAME awk瀏覽的文件名 FNR 瀏覽文件的記錄數 FS 設置輸入域分隔符,等價于命令行 -F選項 NF 瀏覽記錄的域的個數 NR 已讀的記錄數 OFS 輸出域分隔符 ORS 輸出記錄分隔符 RS 控制記錄分隔符

此外,$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,......以此類推。
統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:

#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh

使用printf替代print,可以讓代碼更加簡潔,易讀

awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd

print 和 printf

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

其中print函數的參數可以是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。

如果沒有逗號,參數就串聯在一起而無法區分。這里,逗號的作用與輸出文件的分隔符的作用是一樣的,只是后者是空格而已。

printf函數,其用法和C語言中printf基本相似,可以格式化字符串,輸出復雜時,printf更加好用,代碼更易懂。

格式化字符串輸出(sprintf使用):

其中格式化字符串包括兩部分內容: 一部分是正常字符, 這些字符將按原樣輸出; 另一部分是格式化規定字符, 以"%"開始, 后跟一個或幾個規定字符,用來確定輸出內容格式。

格式符 說明
%d 十進制有符號整數
%u 十進制無符號整數
%f 浮點數
%s 字符串
%c 單個字符
%p 指針的值
%e 指數形式的浮點數
%x %X 無符號以十六進制表示的整數
%o 無符號以八進制表示的整數
%g 自動選擇合適的表示法

[chengmo@centos5 ~]$ awk 'BEGIN{n1=124.113;n2=-1.224;n3=1.2345; printf("%.2f,%.2u,%.2g,%X,%o\n",n1,n2,n3,n1,n1);}' 124.11,18446744073709551615,1.2,7C,174

netstat -anp|awk '{printf "%-8s %-8s %-10s\n",$1,$2,$3}' printf表示格式輸出 %格式化輸出分隔符 -8長度為8個字符 s表示字符串類型 打印每行前三個字段,指定第一個字段輸出字符串類型(長度為8),第二個字段輸出字符串類型(長度為8), 第三個字段輸出字符串類型(長度為10) netstat -anp|awk '$6=="LISTEN" || NR==1 {printf "%-10s %-10s %-10s \n",$1,$2,$3}' netstat -anp|awk '$6=="LISTEN" || NR==1 {printf "%-3s %-10s %-10s %-10s \n",NR,$1,$2,$3}'

字符轉換: echo "65" |awk '{printf "%c\n",$0}' 輸出A awk 'BEGIN {printf "%f\n",999}' 輸出999.000000 格式化輸出:awk '{printf "%-15s %s\n",$1,$3}' temp 將第一個域全部左對齊顯示

print & $0

print 是awk打印指定內容的主要命令 awk '{print}' /etc/passwd == awk '{print $0}' /etc/passwd awk '{print " "}' /etc/passwd //不輸出passwd的內容,而是輸出相同個數的空行,進一步解釋了awk是一行一行處理文本 awk '{print "a"}' /etc/passwd //輸出相同個數的a行,一行只有一個a字母 awk -F":" '{print $1}' /etc/passwd awk -F: '{print $1; print $2}' /etc/passwd //將每一行的前二個字段,分行輸出,進一步理解一行一行處理文本 awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd //輸出字段1,3,6,以制表符作為分隔符

-f 指定腳本文件

awk -f script.awk file BEGIN{ FS=":" } {print $1} //效果與awk -F":" '{print $1}'相同,只是分隔符使用FS在代碼自身中指定 awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test I find 4 blank lines. ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}' //計算文件大小 total size is 17487

-F 指定分隔符

$1 指指定分隔符后,第一個字段,$3第三個字段, \t是制表符 一個或多個連續的空格或制表符看做一個定界符,即多個空格看做一個空格 awk -F":" '{print $1}' /etc/passwd awk -F":" '{print $1 $3}' /etc/passwd //$1與$3相連輸出,不分隔 awk -F":" '{print $1,$3}' /etc/passwd //多了一個逗號,$1與$3使用空格分隔 awk -F":" '{print $1 " " $3}' /etc/passwd //$1與$3之間手動添加空格分隔 awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd //自定義輸出 awk -F: '{print NF}' /etc/passwd //顯示每行有多少字段 awk -F: '{print $NF}' /etc/passwd //將每行第NF個字段的值打印出來 awk -F: 'NF==4 {print }' /etc/passwd //顯示只有4個字段的行 awk -F: 'NF>2{print $0}' /etc/passwd //顯示每行字段數量大于2的行 awk '{print NR,$0}' /etc/passwd //輸出每行的行號 awk -F: '{print NR,NF,$NF,"\t",$0}' /etc/passwd //依次打印行號,字段數,最后字段值,制表符,每行內容 awk -F: 'NR==5{print}' /etc/passwd //顯示第5行 awk -F: 'NR==5 || NR==6{print}' /etc/passwd //顯示第5行和第6行 route -n|awk 'NR!=1{print}' //不顯示第一行

// 匹配代碼塊

//純字符匹配 !//純字符不匹配 ~//字段值匹配 !~//字段值不匹配 ~/a1|a2/字段值匹配a1或a2 awk '/mysql/' /etc/passwd awk '/mysql/{print }' /etc/passwd awk '/mysql/{print $0}' /etc/passwd //三條指令結果一樣 awk '!/mysql/{print $0}' /etc/passwd //輸出不匹配mysql的行 awk '/mysql|mail/{print}' /etc/passwd awk '!/mysql|mail/{print}' /etc/passwd awk -F: '/mail/,/mysql/{print}' /etc/passwd //區間匹配 awk '/[2][7][7]*/{print $0}' /etc/passwd //匹配包含27為數字開頭的行,如27,277,2777... awk -F: '$1~/mail/{print $1}' /etc/passwd //$1匹配指定內容才顯示 awk -F: '{if($1~/mail/) print $1}' /etc/passwd //與上面相同 awk -F: '$1!~/mail/{print $1}' /etc/passwd //不匹配 awk -F: '$1!~/mail|mysql/{print $1}' /etc/passwd

IF 語句

if(表達式) #if ( Variable in Array ) 語句1 else 語句2格式中"語句1"可以是多個語句,如果你為了方便Unix awk判斷也方便你自已閱讀,你最好將多個語句用{}括起來。 Unix awk分枝結構允許嵌套,其格式為:if (expression) { statement; statement; ... ... } if (expression) { statement; } else { statement2; } if (expression) { statement1; } else if (expression1) { statement2; } else { statement3; } [chengmo@localhost nginx]# awk 'BEGIN{ test=100; if(test>90) {print "very good"; } else if(test>60) {print "good"; } else {print "no pass"; } }'very good 每條命令語句后面可以用“;”號結尾。

if 必須用在{}中,且比較內容用()擴起來 awk -F: '{if($1~/mail/) print $1}' /etc/passwd //簡寫 awk -F: '{if($1~/mail/) {print $1}}' /etc/passwd //全寫 awk -F: '{if($1~/mail/) {print $1} else {print $2}}' /etc/passwd //if...else...

awk -F: '{if($3>100) print "large"; else print "small"}' /etc/passwd small small small large small small awk -F: 'BEGIN{A=0;B=0} {if($3>100) {A++; print "large"} else {B++; print "small"}} END{print A,"\t",B}' /etc/passwd //ID大于100,A加1,否則B加1 awk -F: '{if($3<100) next; else print}' /etc/passwd //小于100跳過,否則顯示 awk -F: 'BEGIN{i=1} {if(i<nf) print="" nr,nf,i++="" }'="" etc="" passwd="" <="" span="" style="word-wrap: break-word;"> awk -F: 'BEGIN{i=1} {if(i<nf) {print="" nr,nf}="" i++="" }'="" etc="" passwd<="" span="" style="word-wrap: break-word;"> 另一種形式 awk -F: '{print ($3>100 ? "yes":"no")}' /etc/passwd awk -F: '{print ($3>100 ? $3":\tyes":$3":\tno")}' /etc/passwd while語句 awk -F: 'BEGIN{i=1} {while(i<nf) print="" nf,$i,i++}'="" etc="" passwd ="" <="" div="" style="word-wrap: break-word;"> 7 root 1 7 x 2 7 0 3 7 0 4 7 root 5 7 /root 6

統計某個文件夾下的文件占用的字節數,過濾4096大小的文件(一般都是文件夾):

ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' [end]size is 8.22339 M

循環語句(while,for,do)

awk的循環基本結構

For (element in array) print array[element] awk 'BEGIN {record="123#456#789";split(record,myarray,"#")} END { for (i in myarray) {print myarray[i]} }

1.while語句格式: while(表達式) {語句}例子: [chengmo@localhost nginx]# awk 'BEGIN{ test=100; total=0; while(i<=test) {total+=i;i++; } print total; }' 50502.for 循環for循環有兩種格式:格式1: for(變量 in 數組) {語句}例子: [chengmo@localhost nginx]# awk 'BEGIN{ for(k in ENVIRON) {print k"="ENVIRON[k]; } }'AWKPATH=.:/usr/share/awk OLDPWD=/home/web97 SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass SELINUX_LEVEL_REQUESTED= SELINUX_ROLE_REQUESTED= LANG=zh_CN.GB2312 。。。。。。 說明:ENVIRON 是awk常量,是子典型數組。格式2: for(變量;條件;表達式) {語句}例子: [chengmo@localhost nginx]# awk 'BEGIN{ total=0; for(i=0;i<=100;i++) {total+=i; } print total; }' 50503.do循環 格式: do {語句}while(條件)例子: [chengmo@localhost nginx]# awk 'BEGIN{ total=0; i=0; do {total+=i;i++; }while(i<=100) print total; }' 5050以上為awk流程控制語句,從語法上面大家可以看到,與c語言是一樣的。
有了這些語句,其實很多shell程序都可以交給awk,而且性能是非常快的。
break 當 break 語句用于 while 或 for 語句時,導致退出程序循環。
continue 當 continue 語句用于 while 或 for 語句時,使程序循環移動到下一個迭代。
next 能能夠導致讀入下一個輸入行,并返回到腳本的頂部。這可以避免對當前輸入行執行其他的操作過程。
exit 語句使主輸入循環退出并將控制轉移到END,如果END存在的話。如果沒有定義END規則,或在END中應用exit語句,則終止腳本的執行。

條件表達式

== != > >= awk -F":" '$1=="mysql"{print $3}' /etc/passwd awk -F":" '{if($1=="mysql") print $3}' /etc/passwd //與上面相同 awk -F":" '$1!="mysql"{print $3}' /etc/passwd //不等于 awk -F":" '$3>1000{print $3}' /etc/passwd //大于 awk -F":" '$3>=100{print $3}' /etc/passwd //大于等于 awk -F":" '$3<1{print $3}' /etc/passwd //小于 awk -F":" '$3<=1{print $3}' /etc/passwd //小于等于

邏輯運算符

&& || awk -F: '$1~/mail/ && $3>8 {print }' /etc/passwd //邏輯與,$1匹配mail,并且$3>8 awk -F: '{if($1~/mail/ && $3>8) print }' /etc/passwd awk -F: '$1~/mail/ || $3>1000 {print }' /etc/passwd //邏輯或 awk -F: '{if($1~/mail/ || $3>1000) print }' /etc/passwd

數值運算

awk -F: '$3 > 100' /etc/passwd awk -F: '$3 > 100 || $3 < 5' /etc/passwd awk -F: '$3+$4 > 200' /etc/passwd awk -F: '/mysql|mail/{print $3+10}' /etc/passwd //第三個字段加10打印 awk -F: '/mysql/{print $3-$4}' /etc/passwd //減法 awk -F: '/mysql/{print $3*$4}' /etc/passwd //求乘積 awk '/MemFree/{print $2/1024}' /proc/meminfo //除法 awk '/MemFree/{print int($2/1024)}' /proc/meminfo //取整

輸出分隔符OFS

awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt //輸出字段6匹配WAIT的行,其中輸出每行行號,字段4,5,6,并使用制表符分割字段

輸出處理結果到文件

1. 在命令代碼塊中直接輸出 route -n|awk 'NR!=1{print > "./fs"}' 2. 使用重定向進行輸出 route -n|awk 'NR!=1{print}' > ./fs

數組

因為awk中數組的下標可以是數字和字母,數組的下標通常被稱為關鍵字(key)。值和關鍵字都存儲在內部的一張針對key/value應用hash的表格里。由于hash不是順序存儲,因此在顯示數組內容時會發現,它們并不是按照你預料的順序顯示出來的。數組和變量一樣,都是在使用時自動創建的,awk也同樣會自動判斷其存儲的是數字還是字符串。一般而言,awk中的數組用來從記錄中收集信息,可以用于計算總和、統計單詞以及跟蹤模板被匹配的次數等等。

netstat -anp|awk 'NR!=1{a[$6]++} END{for (i in a) print i,"\t",a[i]}' netstat -anp|awk 'NR!=1{a[$6]++} END{for (i in a) printf "%-20s %-10s %-5s \n", i,"\t",a[i]}' 9523 1 9929 1 LISTEN 6 7903 1 3038/cupsd 1 7913 1 10837 1 9833 1

顯示/etc/passwd的賬戶

awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd 0 root 1 daemon 2 bin 3 sys 4 sync 5 games ......

其他awk用法

向一行awk命令傳值: awk '{if ($5 who | awk '{if ($1==user) print $1 " are in " $2 ' user=$LOGNAME 使用環境變量awk腳本命令: 開頭使用 !/bin/awk -f ,如果沒有這句話自含腳本將不能執行, 例子: !/bin/awk -f # all comment lines must start with a hash '#' # name: student_tot.awk # to call: student_tot.awk grade.txt # prints total and average of club student points # print a header first BEGIN { print "Student Date Member No. Grade Age Points Max" print "Name Joined Gained Point Available" print"=========================================================" } # let's add the scores of points gained (tot+=$6); # finished processing now let's print the total and average point END {print "Club student total points :" totprint "Average Club Student points :" tot/N }

awk腳本

awk腳本可以由一條或多條awk_cmd組成,對于多個awk_cmd,一個awk_cmd完成后,應該另起一行,以便進行隔。? awk_cmd由兩部分組成:?awk_pattern { actions } 另外,在awk命令中直接使用awk_script時,awk_script也可以被分成多行書寫,但必須確保整個awk_script單引號括起來。 awk命令的一般形式: awk '?BEGIN?{ actions } awk_pattern1 { actions } ............ awk_patternN { actions } END?{ actions } ' inputfile 其中 BEGIN { actions } 和 END { actions } 是可選的。 在awk腳本中可以使用AWK本身內置變量,如下:? ARGC?命令行變元個數 ARGV?命令行變元數組 FILENAME?當前輸入文件名 FNR?當前文件中的記錄號 FS?輸入域分隔符,默認為一個空格 RS?輸入記錄分隔符 NF?當前記錄里域個數 NR?到目前為止記錄數 OFS?輸出域分隔符 ORS?輸出記錄分隔符

AWK腳本的運行過程:

awk的流程控制
BEGIN和END:
任何在BEGIN之后列出的操作(在{}內)將在awk開始掃描輸入之前執行,而END之后列出的操作將在掃描完全部的輸入之后執行。因此,通常使用BEGIN來顯示變量和預置(初始化)變量,使用END來輸出最終結果。
例:累計銷售文件xs中的銷售金額(假設銷售金額在記錄的第三字段):

$awk
>'BEGIN { FS=":";print "統計銷售金額";total=0}
>{print $3;total=total+$3;}
>END {printf "銷售金額總計:%.2f",total}' sx
(注:>是shell提供的第二提示符,如要在shell程序awk語句和awk語言中換行,則需在行尾加反斜杠\)
在這里,BEGIN預置了內部變量FS(字段分隔符)和自定義變量total,同時在掃描之前顯示出輸出行頭。而END則在掃描完成后打印出總合計。

?如果BEGIN?區塊存在,awk執行它指定的actions。 ?awk從輸入文件中讀取一行,稱為一條輸入記錄。(如果輸入文件省略,將從標準輸入讀取) ③?awk將讀入的記錄分割成字段,將第1個字段放入變量$1中,第2個字段放入$2,以此類推。$0表示整條記錄。字段分隔符使用shell環境變量IFS或由參數指定。 ?把當前輸入記錄依次與每一個awk_cmd中awk_pattern比較,看是否匹配,如果相匹配,就執行對應的actions。如果不匹配,就跳過對應的actions,直到比較完所有的awk_cmd。 ?當一條輸入記錄比較了所有的awk_cmd后,awk讀取輸入的下一行,繼續重復步驟③和④,這個過程一直持續,直到awk讀取到文件尾。 ?當awk讀完所有的輸入行后,如果存在END,就執行相應的actions。


1)input_file可以是一個文件或者多個文件的列表,awk將按順序處理列表中的每個文件。 2)一條awk_cmdawk_pattern可以省略,省略時不對輸入記錄進行匹配比較就執行相應的actions。一條awk_cmd的actions 也可以省略,省略時默認的動作為打印當前輸入記錄,即{print $0} 。一條awk_cmd中的awk_pattern和actions不能同時省略 3)?BEGIN區塊END區塊別位于awk_script的開頭和結尾。awk_script中只有END區塊或者只有BEGIN區塊是被允許的。如果awk_script中只有BEGIN { actions } ,awk不會讀取input_file。 4)?awk把輸入文件的數據讀入內存,然后操作內存中的輸入數據副本,awk不會修改輸入文件的內容。 5)?awk的總是輸出到標準輸出,如果想讓awk輸出到文件,可以使用重定向。

awk_pattern

awk_pattern模式部分決定actions動作部分何時觸發及觸發actions

awk_pattern可以是以下幾種類型:

1)?正則表達式用作awk_pattern:?/regexp/ 注意,正則表達式regexp必須被/包起來 awk中正則表達式匹配操作中經常用到的字符: ? ? \ ^ $ . [] | () * //?:通用的regexp元字符 ? ? +?: 匹配其前的單個字符一次以上,是awk自有的元字符,不適用于grep或sed等 ? ? ??: 匹配其前的單個字符1次或0次,是awk自有的元字符,不適用于grep或sed等 ? ? 關于正則表達式的更多內容請參《正則表達式》 舉例: ? ? awk '/?*\$0\.[0-9][0-9].*/' input_file ? ? 比如,行內容為$0.99. helllo的行就可以和上面的正則表達式相配 2)?布爾表達式用作awk_pattern,表達式成立時,觸發相應的actions執行。 ? ? ①?表達式中可以使用變量(如字段變量$1,$2等)和/regexp/ ? ? ②?布爾表達式中的操作符: ? ? ? ?關系操作符:?< > <= >= == != ? ? ? ?匹配操作符:?value?~?/regexp/?如果value匹配/regexp/,則返回真 ? ? ? ?value?!~?/regexp/?如果value不匹配/regexp/,則返回真 ? ? ? ? 舉例:?awk '$2?>?10 {print "ok"}' input_file ? ? ? ? awk '$3?~?/^d/?{print "ok"}' input_file ? ? ③?&&(與) 和?||(或) 可以連接兩個/regexp/或者布爾表達式,構成混合表達式!(非) 可以用于布爾表達式或者/regexp/之前。 ? ? ? ?舉例:?awk '($1 < 10 ) && ($2 > 10) {print $0 "ok"}' input_file ? ? ? ?awk '/^d/?||?/x$/?{print $0 "ok"}' input_file ? ? ④?其它表達式用作awk_script,如賦值表達式等 舉例: ? ? ? ?awk '(tot+=$6); END{print "total points :" tot }' input_file?// 分號不能省略 ? ? ? ?awk 'tot+=$6 {print $0} END{print "total points :" tot }' input_file?// 與上面等效 當使用賦值表達式時,表示如果賦值后的變量是數字的話,如果為非0,就匹配,否則不匹配;如果為字符串的話,非空就為匹配,否則不匹配。

awk內置字符串函數: gsub(r,s) ??????????在整個$0中用s替代r awk 'gsub(/name/,"xingming") {print $0}' temp gsub(r,s,t) ????????在整個t中用s替代r index(s,t) ?????????返回s中字符串t的第一位置 awk 'BEGIN {print index("Sunny","ny")}' temp ????返回4 length(s) ??????????返回s的長度 match(s,r) ?????????測試s是否包含匹配r的字符串 awk '$1=="J.Lulu" {print match($1,"u")}' temp ???返回4 split(s,a,fs) ??????在fs上將s分成序列a awk 'BEGIN {print split("12#345#6789",myarray,"#")"' 返回3,同時myarray[1]="12", myarray[2]="345", myarray[3]="6789" sprint(fmt,exp) ????返回經fmt格式化后的exp sub(r,s) ??從$0中最左邊最長的子串中用s代替r(只更換第一遇到的匹配字符串) substr(s,p) ????????返回字符串s中從p開始的后綴部分 substr(s,p,n) ??????返回字符串s中從p開始長度為n的后綴部分

awk字符串連接操作?[chengmo@centos5 ~]$ awk 'BEGIN{a="a";b="b";c=(a""b);print c}' ?????

AWK 內置函數

awk內置函數,主要分以下3種類似:算數函數、字符串函數、其它一般函數、時間函數

1.以下示例了printf函數,它與C語言相似,如下,顯示testAwk文件中行號與第1個字段:$awk '{printf"%03d%s\n",NR,$1}' testAwk 2. 顯示文本文件mydoc匹配(含有)字符串"sun"的所有行$awk '/sun/{print}' mydoc 3.由于顯示整個記錄(全行)是awk的缺省動作,因此可以省略action項$awk '/sun/' mydoc 4.示第一個匹配Sun或sun的行與第一個匹配Moon或moon的行之間的行,并顯示到標準輸出上:$awk '/[Ss]un/,/[Mm]oon/ {print}' myfile 5.下面的示例顯示了內置變量和內置函數length()的使用:$awk 'length($0)>80 {print NR}' myfile 6.UNIX中的用戶進行安全性檢查。方法是考察/etc下的passwd文件,檢查其中的passwd字段(第二字段)是否為為"*"如不為"*",則表示該用戶沒有設置密碼,顯示出這些用戶名(第一字段)。#awk -F: '$2=="" {printf("%s no password!\n",$1' /etc/passwd在這個示例中,passwd文件的字段分隔符是“:”,因此,必須用-F:來更改默認的字段分隔符,這個示例中也涉及到了內置函數printf的使用

一、算術函數:

以下算術函數執行與 C 語言中名稱相同的子例程相同的操作:

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

舉例說明: [chengmo@centos5 ~]$ awk 'BEGIN{OFMT="%.3f";fs=sin(1);fe=exp(10);fl=log(10);fi=int(3.1415);print fs,fe,fl,fi;}' 0.841 22026.466 2.303 3OFMT 設置輸出數據格式是保留3位小數獲得隨機數: [chengmo@centos5 ~]$ awk 'BEGIN{srand();fr=int(100*rand());print fr;}' 78 [chengmo@centos5 ~]$ awk 'BEGIN{srand();fr=int(100*rand());print fr;}' 31 [chengmo@centos5 ~]$ awk 'BEGIN{srand();fr=int(100*rand());print fr;}' 41

二、字符串函數:


函數 說明
gsub( Ere, Repl, [ In ] ) 除了正則表達式所有具體值被替代這點,它和 sub 函數完全一樣地執行,。
sub( Ere, Repl, [ In ] ) 用 Repl 參數指定的字符串替換 In 參數指定的字符串中的由 Ere 參數指定的擴展正則表達式的第一個具體值。sub 函數返回替換的數量。出現在 Repl 參數指定的字符串中的 &(和符號)由 In 參數指定的與 Ere 參數的指定的擴展正則表達式匹配的字符串替換。如果未指定 In 參數,缺省值是整個記錄($0 記錄變量)。
index( String1, String2 ) 在由 String1 參數指定的字符串(其中有出現 String2 指定的參數)中,返回位置,從 1 開始編號。如果 String2 參數不在 String1 參數中出現,則返回 0(零)。
length [(String)] 返回 String 參數指定的字符串的長度(字符形式)。如果未給出 String 參數,則返回整個記錄的長度($0 記錄變量)。
blength [(String)] 返回 String 參數指定的字符串的長度(以字節為單位)。如果未給出 String 參數,則返回整個記錄的長度($0 記錄變量)。
substr( String, M, [ N ] ) 返回具有 N 參數指定的字符數量子串。子串從 String 參數指定的字符串取得,其字符以 M 參數指定的位置開始。M 參數指定為將 String 參數中的第一個字符作為編號 1。如果未指定 N 參數,則子串的長度將是 M 參數指定的位置到 String 參數的末尾 的長度。
match( String, Ere ) 在 String 參數指定的字符串(Ere 參數指定的擴展正則表達式出現在其中)中返回位置(字符形式),從 1 開始編號,或如果 Ere 參數不出現,則返回 0(零)。RSTART 特殊變量設置為返回值。RLENGTH 特殊變量設置為匹配的字符串的長度,或如果未找到任何匹配,則設置為 -1(負一)。
split( String, A, [Ere] ) 將 String 參數指定的參數分割為數組元素 A[1], A[2], . . ., A[n],并返回 n 變量的值。此分隔可以通過 Ere 參數指定的擴展正則表達式進行,或用當前字段分隔符(FS 特殊變量)來進行(如果沒有給出 Ere 參數)。除非上下文指明特定的元素還應具有一個數字值,否則 A 數組中的元素用字符串值來創建。
tolower( String ) 返回 String 參數指定的字符串,字符串中每個大寫字符將更改為小寫。大寫和小寫的映射由當前語言環境的 LC_CTYPE 范疇定義。
toupper( String ) 返回 String 參數指定的字符串,字符串中每個小寫字符將更改為大寫。大寫和小寫的映射由當前語言環境的 LC_CTYPE 范疇定義。
sprintf(Format, Expr, Expr, . . . ) 根據 Format 參數指定的?printf?子例程格式字符串來格式化 Expr 參數指定的表達式并返回最后生成的字符串。

Ere都可以是正則表達式

gsub,sub使用 [chengmo@centos5 ~]$ awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}' this is a test!test!在 info中查找滿足正則表達式,/[0-9]+/ 用””替換,并且替換后的值,賦值給info 未給info值,默認是$0查找字符串(index使用) [wangsl@centos5 ~]$ awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}' ok未找到,返回0正則表達式匹配查找(match使用) [wangsl@centos5 ~]$ awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}' ok截取字符串(substr使用) [wangsl@centos5 ~]$ awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}' s is a tes從第 4個 字符開始,截取10個長度字符串字符串分割(split使用) [chengmo@centos5 ~]$ awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}' 4 4 test 1 this 2 is 3 a分割info,動態創建數組tA,這里比較有意思,awk for …in 循環,是一個無序的循環。 并不是從數組下標1…n ,因此使用時候需要注意。

三、一般函數是:

函數 說明
close( Expression ) 用同一個帶字符串值的 Expression 參數來關閉由 print 或 printf 語句打開的或調用 getline 函數打開的文件或管道。如果文件或管道成功關閉,則返回 0;其它情況下返回非零值。如果打算寫一個文件,并稍后在同一個程序中讀取文件,則 close 語句是必需的。
system(Command ) 執行 Command 參數指定的命令,并返回退出狀態。等同于system?子例程。
Expression | getline [ Variable ] 從來自 Expression 參數指定的命令的輸出中通過管道傳送的流中讀取一個輸入記錄,并將該記錄的值指定給 Variable 參數指定的變量。如果當前未打開將 Expression 參數的值作為其命令名稱的流,則創建流。創建的流等同于調用?popen?子例程,此時 Command 參數取 Expression 參數的值且 Mode 參數設置為一個是 r 的值。只要流保留打開且 Expression 參數求得同一個字符串,則對 getline 函數的每次后續調用讀取另一個記錄。如果未指定 Variable 參數,則 $0 記錄變量和 NF 特殊變量設置為從流讀取的記錄。
getline [ Variable ] < Expression 從 Expression 參數指定的文件讀取輸入的下一個記錄,并將 Variable 參數指定的變量設置為該記錄的值。只要流保留打開且 Expression 參數對同一個字符串求值,則對 getline 函數的每次后續調用讀取另一個記錄。如果未指定 Variable 參數,則 $0 記錄變量和 NF 特殊變量設置為從流讀取的記錄。
getline [ Variable ] 將 Variable 參數指定的變量設置為從當前輸入文件讀取的下一個輸入記錄。如果未指定 Variable 參數,則 $0 記錄變量設置為該記錄的值,還將設置 NF、NR 和 FNR 特殊變量。

打開外部文件(close用法) [chengmo@centos5 ~]$ awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin逐行讀取外部文件(getline使用方法) [chengmo@centos5 ~]$ awk 'BEGIN{while(getline < "/etc/passwd"){print $0;};close("/etc/passwd");}' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin[chengmo@centos5 ~]$ awk 'BEGIN{print "Enter your name:";getline name;print name;}' Enter your name: chengmo chengmo調用外部應用程序(system使用方法) [chengmo@centos5 ~]$ awk 'BEGIN{b=system("ls -al");print b;}' total 42092 drwxr-xr-x 14 chengmo chengmo 4096 09-30 17:47 . drwxr-xr-x 95 root root 4096 10-08 14:01 ..b返回值,是執行結果。

四、時間函數

函數名 說明
mktime( YYYY MM DD HH MM SS[ DST]) 生成時間格式
strftime([format [, timestamp]]) 格式化時間輸出,將時間戳轉為時間字符串?
具體格式,見下表.
systime() 得到時間戳,返回從1970年1月1日開始到當前時間(不計閏年)的整秒數

創建指定時間(mktime使用) [chengmo@centos5 ~]$ awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp);}' 2001年01月01日 星期一 12時12分12秒[chengmo@centos5 ~]$ awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1;}' 2634468求2個時間段中間時間差,介紹了strftime使用方法[chengmo@centos5 ~]$ awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}' 308201392

strftime日期和時間格式說明符

格式描述
%a 星期幾的縮寫(Sun)
%A 星期幾的完整寫法(Sunday)
%b 月名的縮寫(Oct)
%B 月名的完整寫法(October)
%c 本地日期和時間
%d 十進制日期
%D 日期 08/20/99
%e 日期,如果只有一位會補上一個空格
%H 用十進制表示24小時格式的小時
%I 用十進制表示12小時格式的小時
%j 從1月1日起一年中的第幾天
%m 十進制表示的月份
%M 十進制表示的分鐘
%p 12小時表示法(AM/PM)
%S 十進制表示的秒
%U 十進制表示的一年中的第幾個星期(星期天作為一個星期的開始)
%w 十進制表示的星期幾(星期天是0)
%W 十進制表示的一年中的第幾個星期(星期一作為一個星期的開始)
%x 重新設置本地日期(08/20/99)
%X 重新設置本地時間(12:00:00)
%y 兩位數字表示的年(99)
%Y 當前月份
%Z 時區(PDT)
%% 百分號(%)

以上是awk常見 內置函數使用及說明,希望對大家有所幫助。

awk中的自定義函數

原始的awk并不提供函數功能,只有在nawk或較新的awk版本中才可以增加函數
awk函數的定義方法如下:

function 函數名(參數表){ 函數體 }

? ? ? ? 在gawk中允許將function省略為func,但其它版本的awk不允許。在 awk中調用函數比較簡單,其方法與C語言相似,但awk比C語言更為靈活,它不執行參數有效性檢查。換句話說,在你調用函數時,可以列出比函數預計(函 數定義中規定)的多或少的參數,多余的參數會被awk所忽略,而不足的參數,awk將它們置為缺省值0或空字符串,具體置為何值,將取決于參數的使用方 式。在函數中使用形如:return 返回值 格式的語句。

例: 下面的例子演示了函數的使用。在這個示例中,定義了一個名為print_header的函數,該函數調用了兩個參數FileName和 PageNum,FileName參數傳給函數當前使用的文件名,PageNum參數是當前頁的頁號。這個函數的功能是打印(顯示)出當前文件的文件名, 和當前頁的頁號。完成這個功能后,這個函數將返回下一頁的頁號。

nawk >'BEGIN{pageno=1;file=FILENAME >pageno=print_header(file,pageno);#調用函數print_header >printf("當前頁頁號是:%d\n",pageno); >} >#定義函數print_header >function print_header(FileName,PageNum){ >printf("%s %d\n",FileName,PageNum); >PageNum++;return PageNUm; >} >}' myfile 執行這個程序將顯示如下內容: myfile 1 當前頁頁號是:2

NR與FNR: QUOTE: A.awk對多輸入文件的執行順序是,先將代碼作用于第一個文件(一行行讀入),然后該重復的代碼又作用于第二個文件,再作用于第三個文件。 B.awk對多輸入文件的執行順序產生了行序號的問題。當第一個文件執行完,下次讀入第二個文件,那么第二個文件的第一行怎么算呢?如果又計為1的話,那不就兩個1了么?(因為第一個文件也有第一行)。這就是NR和FNR的問題。 ???NR :全局行數(第二個文件的第一行接著第一個文件尾行數順序計數) ???FNR:當前文件自身的行數(不考慮前幾個輸入文件的自身行數及總數) ?????????例如:data1.txt中有40行,data2.txt中有50行,那么awk ‘{}’ data1.txt data2.txt ??????????????????NR ?的值依次為:1,2……40,41,42……90 ???????????????????FNR的值依次為:1,2……40, 1, 2……50? getline函數說明: awk 的 getline語句用于簡單地讀取一條記錄。如果用戶有一個數據記錄類似兩個物理記錄,那么getline將尤其有用。它完成一般字段的分離(設置字段變量$0 FNR NF NR)。如果成功則返回1,失敗則返回0(到達文件尾)。 QUOTE: A.getline從整體上來說,應這么理解它的用法: ????????????當其左右無重定向符 | 或 < 時,getline作用于當前文件,讀入當前文件的第一行給其后跟的變量? ????????????var 或$0(無變量);應該注意到,由于awk在處理getline之前已經讀入了一行,所以getline得到 ????????????的返回結果是隔行的。 ????????????當其左右有重定向符 | 或 < 時,getline則作用于定向輸入文件,由于該文件是剛打開,并沒有被 ????????????awk讀入一行,只是getline讀入,那么getline返回的是該文件的第一行,而不是隔行。 B.getline用法大致可分為三大類(每大類又分兩小類),即總共有6種用法。代碼如下: QUOTE: nawk ‘BEGIN{“cat data.txt”|getline d; print d}’ data2.txt? nawk ‘BEGIN{“cat data.txt”|getline; print $0}’ data2.txt nawk ‘BEGIN{getline d < “data.txt”; print d}’ data2.txt? nawk ‘BEGIN{getline < “data.txt”; print $0}’ data2.txt ??????以上四行代碼均實現“只打印data.txt文件的第一行”(若打印全部行,用循環) eg. nawk ‘BEGIN{FS=”:”;while(getline<”/etc/passwd”>0){print $1}}’ data.txt
QUOTE: nawk ‘{getline d; print d”#”$3}’ data.txt ?awk首先讀入第一行,接著處理getline函數,然后把下一行指定給變量d,再先打印d,由于d后面有換行符,所以后面緊跟的#會覆蓋d,后面的$3同樣也會覆蓋d。 QUOTE: nawk ‘{getline; print $0”#”$3}’ data.txt awk首先讀入第一行接著處理getline函數,然后把下一行指定給$0,現在的$0已經是下一行內容,后面的#和$3(從$0中取)會覆蓋$0的內容。 在awk中,有時需要調用系統工具來完成awk不擅長的工作,awk提供的system命令可以用來執行,但收不到外部工具的輸出結果。好在可以運用getline來滿足這個需求。例如 test.awk: { ???datecommand="/bin/date -j -f \"%d/%b/%Y:%H:%M:%S\" " $olddatestr " \"+%Y%m%d %H%M%S\""; ???datecommand | getline newdatestr? ???close(datecommand); } ? 外部命令需要awk占用一個文件描述符,而awk最多能打開的文件有一個上限,而且不大(比如說16),所以最后做一個close是好習慣。把命令串定義為一個變量也是為了close的時候方便

awk高級輸入輸出

1.讀取下一條記錄:?
? ? ? ? awk的next語句導致awk讀取下一個記錄并完成模式匹配,然后立即執行相應的操作。通常它用匹配的模式執行操作中的代碼。next導致這個記錄的任何額外匹配模式被忽略。?

2.簡單地讀取一條記錄?
? ? ? ? awk 的 getline語句用于簡單地讀取一條記錄。如果用戶有一個數據記錄類似兩個物理記錄,那么getline將尤其有用。它完成一般字段的分離(設置字段變 量$0 FNR NF NR)。如果成功則返回1,失敗則返回0(到達文件尾)。如果需簡單地讀取一個文件,則可以編寫以下代碼:?
例:示例getline的使用?
{while(getline==1)?
{?
#process the inputted fields?
}?
}?
也可以使getline保存輸入數據在一個字段中,而不是通過使用getline variable的形式處理一般字段。當使用這種方式時,NF被置成0,FNR和NR被增值。?
用 戶也可以使用getline<"filename"方式從一個給定的文件中輸入數據,而不是從命令行所列內容輸入數據。此時,getline將完成 一般字段分離(設置字段變量$0和NF)。如果文件不存在,返回-1,成功,返回1,返回0表示失敗。用戶可以從給定文件中讀取數據到一個變量中,也可以 用stdin(標準輸入設備)或一個包含這個文件名的變量代替filename。值得注意的是當使用這種方式時不修改FNR和NR。?

另一種使用getline語句的方法是從UNIX命令接受輸入,例如下面的例子:?
例:示例從UNIX命令接受輸入?
{while("who -u"|getline)?
{?
#process each line from the who command?
}?
}?

當然,也可以使用如下形式:?
"command" | getline variable?

3.關閉文件:?
? ? ? ? awk中允許在程序中關閉一個輸入或輸出文件,方法是使用awk的close語句。?
close("filename")?
filename可以是getline打開的文件(也可以是stdin,包含文件名的變量或者getline使用的確切命令)。或一個輸出文件(可以是stdout,包含文件名的變量或使用管道的確切命令)。?

4.輸出到一個文件:?
? ? ? ? awk中允許用如下方式將結果輸出到一個文件:?
printf("hello word!\n")>"datafile"?
或?
printf("hello word!\n")>>"datafile"?

5.輸出到一個命令?
? ? ? ? awk中允許用如下方式將結果輸出到一個命令:?
printf("hello word!\n")|"sort-t','"

awk與shell script混合編程

因 為awk可以作為一個shell命令使用,因此awk能與shell批處理程序很好的融合在一起,這給實現awk與shell程序的混合編程提供了可能。 實現混合編程的關鍵是awk與shell script之間的對話,換言之,就是awk與shell script之間的信息交流:awk從shell script中獲取所需的信息(通常是變量的值)、在awk中執行shell命令行、shell script將命令執行的結果送給awk處理以及shell script讀取awk的執行結果等等。?

1.awk讀取Shell script程序變量?
在awk中我們可以通過“'$變量名'”的方式讀取sell scrpit程序中的變量。?
例:在下面的示例中,我們將讀取sell scrpit程序中的變量Name,該變量存放的是文本myfile的撰寫者,awk將打印出這個人名。?
$cat writename?
:?
# @(#)?
#?
.?
.?
.?
Name="張三" nawk 'BEGIN {name="'Name'";\ printf("\t%s\t撰寫者%s\n",FILENAME,name");}\?
{...}END{...}' myfile?
.?
.?
.?

2.將shell命令的執行結果送給awk處理?
作為信息傳送的一種方法,我們可以將一條shell命令的結果通過管道線(|)傳遞給awk處理:?
例:示例awk處理shell命令的執行結果?
$who -u | awk '{printf("%s正在執行%s\n",$2,$1)}'?
該命令將打印出注冊終端正在執行的程序名。?

3.shell script程序讀awk的執行結果?
為 了實現shell script程序讀取awk執行的結果,我們可以采取一些特殊的方法,例如我們可以用變量名=`awk語句`的形式將awk執行的結果存放入一個 shell script變量。當然也可以用管道線的方法將awk執行結果傳遞給shell script程序處理。?
例:作為傳送消息 的機制之一,UNIX提供了一個向其所有用戶傳送消息的命令wall(意思是write to all寫給所有用戶),該命令允許向所有工作中的用戶(終端)發送消息。為此,我們可以通過一段shell批處理程序wall.shell來模擬這一程序 (事實上比較老的版本中wall就是一段shell批處理程序:?

$cat wall.shell?
:?
# @(#) wall.shell:發送消息給每個已注冊終端?
#?
cat >/tmp/
#用戶錄入消息文本 who -u | awk '{print $2}' | while read tty ?
do ?
cat /tmp/
>$tty?
done?

在 這個程序里,awk接受who -u命令的執行結果,該命令打印出所有已注冊終端的信息,其中第二個字段是已注冊終端的設備名,因此用awk命令析出該設備名,然后用while read tty語句循環讀出這些文件名到變量(shell script變量)tty中,作為信息傳送的終結地址。?

4.在awk中執行shell命令行----嵌入函數system()?
system()是一個不適合字符或數字類型的嵌入函數,該函數的功能是處理作為參數傳遞給它的字符串。system對這個參數的處理就是將其作為命令處理,也就是說將其當作命令行一樣加以執行。這使得用戶在自己的awk程序需要時可以靈活地執行命令或腳本。?
例:下面的程序將使用system嵌入函數打印用戶編制好的報表文件,這個文件存放在名為myreport.txt的文件中。為簡約起見,我們只列出了其END部分:?
.?
.?
.?
END {close("myreport.txt");system("lp myreport.txt");}?
在這個示例中,我們首先使用close語句關閉了文件myreport.txt文件,然后使用system嵌入函數將myreport.txt送入打印機打印。?

入門實例

假設last -n 5的輸出如下 [root@www ~]# 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個帳號 #last -n 5 | awk '{print $1}' root root root dmtsai root awk工作流程是這樣的:讀入有'\n'換行符分割的一條記錄,然后將記錄按指定的域分隔符劃分域,填充域, $0則表示所有域,$1表示第一個域,$n表示第n個域。 默認域分隔符是"空白鍵" 或 "[tab]鍵",所以$1表示登錄用戶,$3表示登錄用戶ip,以此類推。 如果只是顯示/etc/passwd的賬戶#cat /etc/passwd |awk -F ':' '{print $1}' root daemon bin sys 這種是awk+action的示例,每行都會執行action{print $1}。 -F指定域分隔符為':'。 如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以tab鍵分割#cat /etc/passwd |awk -F ':' '{print $1"\t"$7}' root /bin/bash daemon /bin/sh bin /bin/sh sys /bin/s 如果只是顯示/etc/passwd的賬戶和賬戶對應的shell,而賬戶與shell之間以逗號分割, 而且在所有行添加列名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工作流程是這樣的: 先執行BEGING,然后讀取文件,讀入有/n換行符分割的一條記錄,然后將記錄按指定的域分隔符劃分域,填充域, $0則表示所有域,$1表示第一個域,$n表示第n個域,隨后開始執行模式所對應的動作action。 接著開始讀入第二條記錄······直到所有的記錄都讀完,最后執行END操作。搜索/etc/passwd有root關鍵字的所有行#awk -F: '/root/' /etc/passwd root:x:0:0:root:/root:/bin/bash 這種是pattern的使用示例,匹配了pattern(這里是root)的行才會執行action(沒有指定action,默認輸出每行的內容)。搜索支持正則,例如找root開頭的: awk -F: '/^root/' /etc/passwd 搜索/etc/passwd有root關鍵字的所有行,并顯示對應的shell # awk -F: '/root/{print $7}' /etc/passwd /bin/bash 這里指定了action{print $7}

應用1 awk -F: '{print NF}' helloworld.sh //輸出文件每行有多少字段 awk -F: '{print $1,$2,$3,$4,$5}' helloworld.sh //輸出前5個字段 awk -F: '{print $1,$2,$3,$4,$5}' OFS='\t' helloworld.sh //輸出前5個字段并使用制表符分隔輸出 awk -F: '{print NR,$1,$2,$3,$4,$5}' OFS='\t' helloworld.sh //制表符分隔輸出前5個字段,并打印行號 應用2 awk -F'[:#]' '{print NF}' helloworld.sh //指定多個分隔符: #,輸出每行多少字段 awk -F'[:#]' '{print $1,$2,$3,$4,$5,$6,$7}' OFS='\t' helloworld.sh //制表符分隔輸出多字段 應用3 awk -F'[:#/]' '{print NF}' helloworld.sh //指定三個分隔符,并輸出每行字段數 awk -F'[:#/]' '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12}' helloworld.sh //制表符分隔輸出多字段 應用4 計算/home目錄下,普通文件的大小,使用KB作為單位 ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",sum/1024,"KB"}' ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",int(sum/1024),"KB"}' //int是取整的意思 應用5 統計netstat -anp 狀態為LISTEN和CONNECT的連接數量分別是多少 netstat -anp|awk '$6~/LISTEN|CONNECTED/{sum[$6]++} END{for (i in sum) printf "%-10s %-6s %-3s \n", i," ",sum[i]}' 應用6 統計/home目錄下不同用戶的普通文件的總數是多少? ls -l|awk 'NR!=1 && !/^d/{sum[$3]++} END{for (i in sum) printf "%-6s %-5s %-3s \n",i," ",sum[i]}' mysql 199 root 374 統計/home目錄下不同用戶的普通文件的大小總size是多少? ls -l|awk 'NR!=1 && !/^d/{sum[$3]+=$5} END{for (i in sum) printf "%-6s %-5s %-3s %-2s \n",i," ",sum[i]/1024/1024,"MB"}' 應用7 輸出成績表 awk 'BEGIN{math=0;eng=0;com=0;printf "Lineno. Name No. Math English Computer Total\n";printf "------------------------------------------------------------\n"}{math+=$3; eng+=$4; com+=$5;printf "%-8s %-7s %-7s %-7s %-9s %-10s %-7s \n",NR,$1,$2,$3,$4,$5,$3+$4+$5} END{printf "------------------------------------------------------------\n";printf "%-24s %-7s %-9s %-20s \n","Total:",math,eng,com;printf "%-24s %-7s %-9s %-20s \n","Avg:",math/NR,eng/NR,com/NR}' test0 [root@localhost home]# cat test0 Marry 2143 78 84 77 Jack 2321 66 78 45 Tom 2122 48 77 71 Mike 2537 87 97 95 Bob 2415 40 57 62

附錄:?

1.awk的常規表達式元字符?
\ 換碼序列?
^ 在字符串的開頭開始匹配?
$ 在字符串的結尾開始匹配?
. 與任何單個字符串匹配?
[ABC] 與[]內的任一字符匹配?
[A-Ca-c] 與A-C及a-c范圍內的字符匹配(按字母表順序)?
[^ABC] 與除[]內的所有字符以外的任一字符匹配?
Desk|Chair 與Desk和Chair中的任一個匹配?
[ABC][DEF] 關聯。與A、B、C中的任一字符匹配,且其后要跟D、E、F中的任一個字符。?
* 與A、B或C中任一個出現0次或多次的字符相匹配?
+ 與A、B或C中任何一個出現1次或多次的字符相匹配?
? 與一個空串或A、B或C在任何一個字符相匹配?
(Blue|Black)berry 合并常規表達式,與Blueberry或Blackberry相匹配?

2.awk算術運算符?
運算符 用途?
------------------?
x^y x的y次冪?
x**y 同上?
x%y 計算x/y的余數(求模)?
x+y x加y?
x-y x減y?
x*y x乘y?
x/y x除y?
-y 負y(y的開關符號);也稱一目減?
++y y加1后使用y(前置加)?
y++ 使用y值后加1(后綴加)?
--y y減1后使用y(前置減)?
y-- 使用后y減1(后綴減)?
x=y 將y的值賦給x?
x+=y 將x+y的值賦給x?
x-=y 將x-y的值賦給x?
x*=y 將x*y的值賦給x?
x/=y 將x/y的值賦給x x%=y 將x%y的值賦給x?
x^=y 將x^y的值賦給x?
x**=y 將x**y的值賦給x?

3.awk允許的測試:?
操作符 含義?
x==y x等于y?
x!=y x不等于y?
x>y x大于y?
x>=y x大于或等于y?
x<y x小于y?
x<=y x小于或等于y??
x~re x匹配正則表達式re??
x!~re x不匹配正則表達式re??

4.awk的操作符(按優先級升序排列)?
= 、+=、 -=、 *= 、/= 、 %=?
||?
&&?
> >= < <= == != ~ !~?
xy (字符串連結,'x''y'變成"xy")?
+ -?
* / %?
++ --?

5.awk內置變量(預定義變量)?

說明:表中v項表示第一個支持變量的工具(下同):A=awk,N=nawk,P=POSIX awk,G=gawk?
V 變量 含義 缺省值?
--------------------------------------------------------?
N ARGC 命令行參數個數?
G ARGIND 當前被處理文件的ARGV標志符?
N ARGV 命令行參數數組?
G CONVFMT 數字轉換格式 %.6g?
P ENVIRON UNIX環境變量?
N ERRNO UNIX系統錯誤消息?
G FIELDWIDTHS 輸入字段寬度的空白分隔字符串?
A FILENAME 當前輸入文件的名字?
P FNR 當前記錄數?
A FS 輸入字段分隔符 空格?
G IGNORECASE 控制大小寫敏感0(大小寫敏感)?
A NF 當前記錄中的字段個數?
A NR 已經讀出的記錄數?
A OFMT 數字的輸出格式 %.6g?
A OFS 輸出字段分隔符 空格?
A ORS 輸出的記錄分隔符 新行?
A RS 輸入的記錄他隔符 新行?
N RSTART 被匹配函數匹配的字符串首?
N RLENGTH 被匹配函數匹配的字符串長度?
N SUBSEP 下標分隔符 "\034"?

6.awk的內置函數?
V 函數 用途或返回值?
------------------------------------------------?
N gsub(reg,string,target) 每次常規表達式reg匹配時替換target中的string?
N index(search,string) 返回string中search串的位置?
A length(string) 求串string中的字符個數?
N match(string,reg) 返回常規表達式reg匹配的string中的位置?
N printf(format,variable) 格式化輸出,按format提供的格式輸出變量variable。?
N split(string,store,delim) 根據分界符delim,分解string為store的數組元素?
N sprintf(format,variable) 返回一個包含基于format的格式化數據,variables是要放到串中的數據?
G strftime(format,timestamp) 返回一個基于format的日期或者時間串,timestmp是systime()函數返回的時間?
N sub(reg,string,target) 第一次當常規表達式reg匹配,替換target串中的字符串?
A substr(string,position,len) 返回一個以position開始len個字符的子串?
P totower(string) 返回string中對應的小寫字符?
P toupper(string) 返回string中對應的大寫字符?
A atan(x,y) x的余切(弧度)?
N cos(x) x的余弦(弧度)?
A exp(x) e的x冪?
A int(x) x的整數部分?
A log(x) x的自然對數值?
N rand() 0-1之間的隨機數?
N sin(x) x的正弦(弧度)?
A sqrt(x) x的平方根?
A srand(x) 初始化隨機數發生器。如果忽略x,則使用system()?
G system() 返回自1970年1月1日以來經過的時間(按秒計算)




總結

以上是生活随笔為你收集整理的linux命令终极系列awk的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。