GNU awk
·文本處理三工具:grep,sed,awk
grep,egrep,fgrep:文本過濾工具:pattern
sed:行編輯器
模式空間、保持空間
awk:報告生成器,格式化文本輸出:
AWK:Aho,Weinberger,Kernighan –> New AWK, NAWK
GNU awk,gwak
·gawk – pattern scanning and processing language
基本用法:gawk [options] 'program' FILE …
program:PATTERN{ACTION STATEMENTS}
語句之間用分號分隔
print,printf
選項:
-F:指明輸入時用到的字段分隔符
-v var=value:自定義變量
awk中的變量不給初始值默認是0
·awk工作原理
第一步:執行BEGIN{action;… } 語句塊中的語句
第二步:從文件或標準輸入(stdin) 讀取一行,然后執行pattern{action;… } 語句塊,它逐行掃描文件,從第一行到最后一行重復這個過程,直到文件全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{action;…} 語句塊
BEGIN 語句塊在awk 開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通??梢詫懺贐EGIN語句塊中
END語句塊在awk從輸入流中讀取完所有的行之后即被執行,比如打印所有行的分析結果這類信息匯總都是在END 語句塊中完成,它也是一個可選語句塊
pattern 語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供pattern 語句塊,則默認執行{ print },即打印每一個讀取到的行,awk讀取的每一行都會執行該語句塊
1、print
print item1,item2,…..
要點:
(1):逗號分隔符
(2):輸出的各item可以字符串,也可以是數值;當前記錄的字段、變量或awk的表達式
(3):如省略item,相當于print $0
字段 $1,$2,$3 以-F指定的分隔符對每行切片產生的字段,不指定-F默認是空格
awk -F: '{print $0}' /etc/passwd
awk -F: '{print $1"\t"$3}' /etc/passwd
2、變量
2.1 內建變量
FS:input field seperator,默認為空白字符
OFS:output field seperator,默認為空白字符
RS:input record seperator,輸入時的換行符
ORS:output record seperator,輸出時的換行符
NF:number of field,字段數量
區別:{print NF},{print $NF}
NR:number of record,行數
FNR:各文件分別計數;行數
FILENAME:當前文件名
ARGC:命令行參數的個數
ARGV:數組,保存的是命令行所給定的各參數
2.2 自定義變量
(1) -v var=value
變量名區分字符大小寫
每個-v 指明一個變量
(2) 在program中直接定義
awk -v test='hello gawk' '{print test}' /etc/fstab
awk 'BEGIN{test="hello,gawk";print test}'
3、printf命令
格式化輸出:printf FORMAT,item1,item2
(1) FORMAT(格式符)必須給出
(2) 不會自動換行,余姚顯示給出換行控制符,\n
(3) FORMAT中需要分別為后面的每個item指定一個格式化符號
格式符:
%c:顯示字符的ASCII碼
%d,%i:顯示十進制整數
%e,%E:科學計數法數值顯示
%f:顯示為浮點數
%g,%G:以科學計數法或浮點形式顯示數值
%s:顯示字符串
%u:無符號整數
%%:顯示%自身
修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點后的進度
%3.1f
-:左對其
默認是右對其
+:顯示數值的符號
awk -F: '{printf "Username: %s\n",$1}' /etc/passwd
awk -F: '{printf "Username: %-15sUID:%d\n",$1,$3}' /etc/passwd
4、操作符
算術操作符:
x+y,x-y,x/y,x^y,x%y
-x
+x:轉換其數值
字符串操作符:沒有符號的操作符,字符串連接誒
賦值操作符:
=,+=,-=,*=,/=,%=,^=
++,–
比較操作符:
>,>=,<,<=,!=,==
模式匹配符:
~:是否匹配
!~:是否不匹配
邏輯操作符:
&&
||
!
函數調用:
function_name(argu1,argu2,….)
條件表達式:<三目運算符>
selector?if-true-expression:if-false-expression
# awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or SysUser";printf "%s15s:%-s\n",$1,usertype}' /etc/passwd
5、PATTERN——確切表示應該為行定位符
(1) empty:空模式,匹配每一行
(2) /regular expression/:僅處理能夠被此處的模式匹配到的行
(3) relational expression:關系表達式;結果有“真”有“假”;結果為“真”才會被處理
真:結果為非0,或非空字符串
(4) line ranges:行范圍
startline,endline:/pat1/,/pat2/
注意:不支持直接給出數字的格式
# awk -F: '(NR>=2&&NR<+10){print $1}' /etc/passwd
(5)BEGIN/END模式
BEGIN{}:僅在開始處理文件中的文本之前執行一次
END{}:僅在文本處理完成后執行一次
awk '!0' /etc/passwd
seq 10 | awk '{i=!i;print i}'
awk -F: 'BEGIN{print " USER UID \n —————"}{print $1,$3}END{print "=============="}' /etc/passwd
6、常用的action
(1) Expressions
(2) Control statements:if,while等
(3) Compound statements:組合語句
(4) input statements
(5) output statements
7、控制語句
if(condition) {statements}
if(condition) {statements} else {statements}
while(condition) {statements}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array
exit
{statements}
7.1 if-else
語法:if(condition) {statements}
# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
# awk '{if(NF>5) print $0}' /etc/fstab
# df -h | awk -F% '/^\/dev/{print $1}' | awk '$NF>=80{print $1,$5}'
使用場景:對awk取得的整行或某個字段做條件判斷
7.2 while循環
語法:while(condition) statement
條件“真”,進入循環;條件為“假”,退出循環
使用場景:對一行內的多個字段逐一類似處理時使用,對數組中的各元素逐一處理時使用
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) { print $i,length($i); i++}}' /etc/grub2.cfg
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg
7.3 do-while循環
語法:do statement while(condition)
意義:至少執行一次循環體
# awk 'BEGIN{ total=0;i=0;do{total+=i;i++;}while(i<=100);print total}'
7.4 for循環
語法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
特殊用法:能夠遍歷數組中的元素;
語法:for(var in array) {for-body}
7.5 switch語句
語法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement}
7.6 break和continue語句
break [n]
continue [n]
# awk 'BEGIN{sum=0;for(i=1;i<=100;i++) {if(i%2==0){continue}sum+=i}print sum}'
# awk 'BEGIN{sum=0;for(i=1;i<=100;i++) {if(i==66){break}sum+=i}print sum}'
7.7 next語句
提前結束對本行處理而直接進入下一行處理(awk自身循環)
# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
8、array
·關聯數組:array[index-expression]
·index-expression:
(1)可使用任意字符串
(2)如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串”
若要判斷數組中是否存在某元素,要使用“index in array <for循環的特殊用法>”格式進行
weekdays[mon]="Monday"
·若要遍歷數組中的每個元素,要使用for循環:
for(var in array) {for-body}
awk 'BEGIN{weekdays["mon"]="Monday"; weekdays["tue"]="Tuesday"; print weekdays["mon"]}'
awk '!a[$0]++' dupfile
去掉文件中重復的行
注意:var會遍歷array的每個索引
# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(index in state) { print index,state[index]}}'
# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
練習1、統計/etc/fstab 文件中每個文件系統類型出現的次數:
# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
練習2、統計/etc/fstab 文件中每個單詞出現的次數;
# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
9、函數
9.1 內置函數
數值處理:
rand():返回0-1之間的一個隨機數
awk中使用隨機數要配置srand(種子)使用
# awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
字符串處理:
length([s]):返回指定字符串的長度
sub(r,s,[t]):以r表示的模式來查找t字符串中是否有匹配的內容,并將其第一次出現替換為s所表示的內容
gsub(r,s,[t]):以r表示的模式來查找t字符串中是否有匹配的內容,并將其所有出現均替換為s所表示的內容
split(s,a[,r]):以r為分割符切割字符s,并將切割后的結果保存至a所表示的數組中
# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++} END{for (i in count) {print i,count[i]}}'
9.2 自定義函數
格式:
function name ( parameter, parameter, … ) {
statements
return expression
}
示例:
#cat fun.awk
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{a=3;b=2;print max(a,b)}
#awk –f fun.awk
《sed和awk》
10、調用shell命令
system命令
空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk 的變量外其他一律用""引用起來。
# awk BEGIN'{system("hostname") }'
# awk 'BEGIN{score=100; system("echo your score is " score) }'
練習1、求每班總成績和平均成績
[root@localhost ~]# cat score.txt zhangsan 1 100 lisi 1 95 wangwu 2 90 cuihua 1 80 meigui 2 90 honghua 2 85 [root@localhost ~]# awk 'BEGIN{sum1=0; sum2=0; num1=0; num2=0}{if($2==1){sum1+=$3;num1++}else{sum2+=$3;num2++}} \ END{ num1=sum1/num1;num2=sum2/num2;printf "one class sum score: %s\taverage score: %s\ntwo class sum score: %s\t \ average score: %s\n", sum1,num1,sum2,num2}' score.txt one class sum score: 275 average score: 91.6667 two class sum score: 265 average score: 88.3333
原創文章,作者:megedugao,如若轉載,請注明出處:http://www.www58058.com/47995