您好,登錄后才能下訂單哦!
awk(gawk):報告生成器,格式化文本輸出:awk,gawk
基本用法:gawk [options] ‘program’ FILE ...
program: PATTERN{ACTION STATEMENT};可以有多個,語句之間用分號分隔
print,printf
選項:
-F:指明輸入數據時用到的字段分隔符
-v var=value:自定義變量;
變量:
1)內建變量
FS:input field seperator(輸入字段分隔符,默認為空白字符)
#awk -v FS=':' '{print $1}' /etc/passwd
#awk -F: ‘{print $1}’ /etc/passwd(這個命令和上面的命令效果是一樣的)
注:使用FS可以一次使用多個字符做為分隔符;例:awk -v FS="[,:]" '{print $3,$1,$2}' d.txt
OFS:output field seperator(輸出字段分隔符,默認為空白字符)
#awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd
RS:input record seperator,輸入時的換行符;
ORS:output record seperator,輸出時的換行符;
NF:number of field,每一行字段數量
{print NF},{print $NF}(在awk中引用變量不需要加$符號)
一行中的最后一個字段用$NF表示
NR:number of record,處理過的行數
#awk ‘{print NR}’ /etc/fstab
FNR:每一個文件處理過的行數
#awk ‘{print FNR}’ /etc/fstab /etc/issue
FILENAME:當前正在處理的文件的文件名
#awk ‘{print FILENAME}’ /etc/fstab
ARGC:命令行參數的個數
#awk 'BEGIN{print ARGC}' /etc/fstab
ARGV:數組,保存的是命令行所給定的各參數
#awk 'BEGIN{print ARGV[0]}' /etc/fstab
2)自定義變量
-v var=value
變量名區分字符大小寫;
#awk -v test='Hello gawk' 'BEGIN{print test}'
在program中直接定義
#awk 'BEGIN{test="Hello gawk";print test}'
操作符:
算術運算操作符:
x+y,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>=1000?usertype="Common User":usertype="SysadminUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
printf格式化輸出:
格式化輸出的命令:printf FORMAT,item1,item2,...
(1)FORMAT必須要給出
(2)Printf不會自動換行,如果需要換行,需要顯式給出換行控制符,\n
(3)FORMAT中需要分別為后面的每個item指定一個格式化符號
格式符:
%c:顯示字符的ASCII碼;
%d,%i:顯示十進制整數;
%e,%E:科學計數法計數顯示
%f:顯示為浮點數;
%g,%G:以科學計數法或浮點形式顯示數值;
%s:顯示字符串;
%u:無符號整數;
%%:顯示%自身;
修飾符:
#[.#]:第一個數字用來控制顯示的寬度:第二個#表示小數點后的精度,可以省略
#awk -F: '{printf "Username:%20s UID:%d\n",$1,$3}' /etc/passwd
-:左對齊
#awk -F: '{printf "Username:%-20s UID:%d\n",$1,$3}' /etc/passwd
+:顯示數值的符號,負數顯示為-,正數顯示為+號
#awk -F: '{printf "Username:%20s UID:%+d\n",$1,$3}' /etc/passwd
模式匹配:
1)empty:空模式,匹配每一行;
2)/regular expression/:僅處理能夠被此處的模式匹配到的行
#awk '/^#/{print}' /etc/fstab
#awk '!/^#/{print}' /etc/fstab
3)relational expression:關系表達式,結果有”真“有“假”:結果為”真“才會被處理:真:結果為非0值,非空字符串;
#awk -F: '$3>=1000{print $1,$3}' /etc/passwd
#awk -F: '$3<=1000{print $1,$3}' /etc/passwd
#awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
#awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
4)line ranges:地址定界(行范圍)
#awk -F: '/^root/,/^liu/{print $1}' /etc/passwd
注意:不支持直接給出數字的格式
#awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
5)BEGIN/END模式
BEGIN{}:表示僅在開始處理文件中每一行文本之前執行一次的程序;
END{};表示僅在文本處理完成之后,命令結束之前執行一次的程序;
條件判斷,循環:
條件判斷:
if(condition){statements}
例:#awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd
if(confition){statements} else {statements}
例:#awk -F: '{if($3>=1000) {printf "Commono user:%s\n",$1} else {printf "root orSysuser:%s\n",$1}}' /etc/passwd
循環:
while(condition) {statements}:條件為“真”,進入循環:條件為“假”,退出循環
例:#awk -v i=1 'BEGIN{while(i<=4){print i;++i}}'
for(expr1;expr2;expr3) {statements}
例:#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' grub2.cfg
for(var in array) {for-body}:常用于遍歷數組中的元素
例:#netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) {print i,state[i]}}'
#awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /usr/logcal/nginx/logs/access.log
跳出循環:
break:跟出整個循環
continue:跳出當前循環,進入下一個循環
next:提前結束對本行的處理,直接進入下一行
例:#awk -F: '{if($3%2!=0) next;print $1,$3}' /etc/passwd
數組:
關聯數組是awk一個獨特的特征,它的一個強大的功能就是可以使用字符串作為一個數據的下標
Index-erpression:
若某數組事先不存在,則在使用時直接創建,并將其初始化為空的數組;
可使用任意字符串作為下標;字符串要使用雙引號;
若要判斷數組中是否存在某元素,要使用”index in array“格式進行:
若要遍歷數組中的每個元素,要使用for循環;
for(var in array) {for-body}
注意:var會遍歷array的每個索引;
刪除數組中的元:
delete array[subscript]
函數:
awk的內置函數可以分為兩組:算術函數和字符串函數
1)內置函數
數值處理:
rand():返回0和1之間一個隨機數;
字符串處理;
length([s]):返回指定字符串的長度
sub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,并將其第一次出現替換為s所表示的內容;
gub(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]}}'
getline函數:
getline函數的作用是從文本中讀取內容,也可以從管道中接收內容
getline函數的用法比較特殊,不能使用getline(),它的語法不允許有圓括號,只能使用getline
從文件中讀取內容:getline < "a" --> 從文件a中讀取內容,小于號表示重定向,不能理解為小于號
將讀取的內容賦給一個變量:getline name < "a"
2)自定義函數
練習:
1.統計/etc/fstab文件中每個文件系統類型出現的次數;
2.統計指定文件中每個單詞出現的次數;
3.統計下面語句中,每個單詞及字符出現的個數
the squid project provides a number of resources toassist users design,
implement and support squid installations. Please browsethe documentation
and support ections for more infomation
4.統計grade.txt中的分數的平均數
mona 70 77 85 83 70 89
john 85 92 78 94 88 91
andrea 89 90 85 94 90 95
jasper 84 88 80 92 84 82
dunce 64 80 60 60 61 62
ellis 90 98 89 96 96 92
5.在問題4的基礎上統計grade.txt中班級平均分數,并以A,B,C,D為同學平均分做出分類并統計?
6.文件test中有如下內容:
zhangsan 80
lisi 81.5
wangwu 93
zhangsan 85
lisi 88
wangwu 97
zhangsan 90
lisi 92
wangwu 88
要求輸出格式:(average:平均成績,total:總成績)
name#######average#######total
zhangsan xxx xxx
lisi xxx xxx
wangwu xxx xxx
答案:
1.
#awk '!/^#/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
2.
#awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
3.
統計字符出現的次數
#grep -o "\w" c.txt | awk '{s[$1]++}END{for (key in s) print key,s[key]}'
統計單詞出現的次數
#awk 'BEGIN{RS="[ .,]+"}{words[$1]++}END{for(i in words){print i,words[i]}}' c.txt
4.
[root@localhost ~]# cat 8.awk { total=0 for(i=2;i<=NF;i++){ total += $i avg=total/(NF-1) } print NR,$1,avg }
5.
[root@localhost ~]# cat grades.awk BEGIN{OFS="\t"} { total=0 for(i=2;i<=NF;i++){ total += $i avg=total/(NF-1) } student_avg[NR]=avg if(avg>=90) grade="A" else if(avg>=80) grade="B" else if(avg>=70) grade="C" else if(avg>=60) grade="D" else grade="F" ++class_grade[grade] } END{ for(x=1;x<=NR;x++){ class_avg_total += student_avg[x] print student_avg[x] } class_average=class_avg_total/NR for(x=1;x<=NR;x++){ if(student_avg[x]>=class_average) ++above_average else ++below_average } print "" print "班級平均分數:",class_average print "大于平均分數有:"above_average" 位同學!" print "低于平均分數有:"below_average" 位同學!" for(letter_grade in class_grade){ print letter_grade":" class_grade[letter_grade] | "sort" } }
6.
[root@localhost ~]# awk 'BEGIN{print "name\taverage\ttotal"}{a[$1]+=$2;b[$1]++}END{for(i in a){print i"\t"a[i]/b[i]"\t"a[i]}}' test name average total zhangsan 85 255 wangwu 92.6667 278 lisi 87.1667 261.5 解析: a[$1]+=$2:把第一列作為數組的下標,累計相加的結果作為對應數組的元素(即值) b[$1]++:把第一列作為數組的下標,每出現一次計數器加1并且作為數組的元素(即值)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。