文本處理工具:grep,sed,awk
awk:報告生成器,格式化文本輸出
AWK: Aho ,Weinberger,Kernighan
gawk:GNU awk
gawk – pattren scanning and processing language
基本語法:gawk [options ] ‘program’ FILE….
program:PATTERN{ACTION STATEMENTS}
語句之間用分號分隔
選項:
-F:指明輸入時用到的字段分隔符
-v:var=value:自定義變量
-
print
print item1,item2,…..
要點:
1.以逗號作為分隔符
2.輸出的各item可以是字符串,也可以是數字。也可以是當前記錄的字段,變量或者awk的表達式
3.如果省略item,相當于print $0
實例:
注意print里面的字符要用引號 引起來
如果是變量就不要用引號了
省略item相當于print $0,而print “”相當于空,而print “ ”表現是空格
2.變量
a,內建變量(分隔符)
FS:inuput field seperator,默認為空白字符
OFS: output field seperator,默認為空白字符
RS:inuput record seperator,輸入的換行符
ORS:output record seperator,輸出的換行符
因為此處只定義了輸入時換行符為“”,并沒有定義輸出換行符,所有默認,在輸出的時候空格時要換行
,原默認要換行的時候也會換行
NF:number of field,字段數量
{print NF} 顯示字段數 {print 1}
,{print $NF}顯示最后一個字段,類似于{print $1}
NR: number of field,行數 (如果兩個文件一起顯示,會直接連在一起,不會分開計數)
{print NR} 顯示行數
FNR:file number of field, 各文件分開計數行數
FILENAME:當前文件名
ARGC:命令行參數的個數
ARGV:數組,保存的是命令行所給定的各參數
b.自定義變量
1.-v var=value
變量名區分大小寫
2.在program中直接定義
3.printf命令
格式化輸出:printf FORMAT ,item1,item2,….
1.FORMAT是必須要給出的
2.不會自動換行,需要顯示給出換行控制符,\n
3.FORMAT需要分別為后面的每個item指定一個格式化符號
格式符:
%c:顯示字符的ASCII碼
%d,%i:顯示十進制整數
%e,%E:科學計數法數值顯示
%f:顯示為浮點數
%g,%G:以科學計數法或浮點形式顯示數值
%s:顯示字符串
%u:無符號整數
%%:顯示%自身
換行符記得加上,不然看起來就很蠢了!!
每個item都要有一個FORMAT,否則item就不成立了,不顯示了
修飾符:
#[.#]格式符:
例如%3.1f==>第一個數字控制顯示寬度,第二個數字表示小數點后的精度
-:表示左對齊,默認為右對齊
+:表示數值的符號
表示左對齊
默認為右對齊
4.操作符
算術運算操作符
+,-,*,/,^,% 依次為加減乘除 次方取模
-x:負值
+x:轉換為數值
字符串操作符:沒有符號的操作符,字符串連接
賦值操作符
=,+=,-=,*=,/=,^=,%=
比較操作符:
>,>=,<,<=,!=,==
模式匹配:
~:是否匹配
!~:是否不匹配
邏輯操作符:
&&: 與
||:或
?。悍?/p>
顯示/etc/passwd文件中uid=0或者大于1000的行顯示第1,3列,分隔符為”:“
顯示/etc/passwd文件中uid大于等于0小于等于1000的行顯示第1,3列,分隔符為”:“
顯示/etc/passwd文件中uid不等于0的行顯示第1,3列,分隔符為”:“
函數調用:
function_name(argu1,argu2,…..)
條件表達式:
selector ? if-true-expression:if-false-expression
如果為真執行true,否則執行false
實例:
如果uid大于1000,則usertype為common,否則為system,,輸出每行第一列及變量usertype
awk -F: '{$3>=1000?usertype="common":usertype="system";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
5.PATTERN
1.empty:空模式,匹配每一行;
2./regular expression/:僅處理被此處的模式匹配的行
!/regular expression/:僅處理被此模式匹配的行之外的行
例:顯示以UUID開頭的行,顯示第一列,可個為分隔符
顯示不以UUID開頭的行,顯示第一列,可個為分隔符
3.relational expression:關系表達式,結果有”真“有”假“,結果為”真“才會被處理
真:結果為非0值,非空字符串
假:結果為空字符串或0值
示例:
4.line ranges:行范圍
startline,endline: /pat1/,/pat2/不支持直接給出數字格式
顯示從以root開頭的行開始,到以nobody開頭的行結束,顯示第一列,以”:“為分隔符
顯示行號小于10或者大于40的行,取出第一列,分隔符為”:“
5.NEGIN/END模式
BEGIN{}:僅在開始處理文件中的文本之前執行一次
END{}:僅在文本處理完成之后執行一次
示例:
結果為真處理,為假不處理
顯示偶數行和奇數行
此例來解釋為何上面是奇數和偶數
說明:i初始值為0,第一行i=!i,則i=1,結果為真,處理,所以上面第一行顯示
第二行時,i初始值為1,i=!i,則i=0,結果為假,不處理,所有上面第二行沒顯示,
下面就是循環賦值了,每到技奇數行i=1,偶數行i=0,所以才有上面的效果
(注意1為真,0為假,非1的結果就是假了,而非0的結果就是真了)
如果我們使得i的初始值為真,那么結果就和上面的相反了,顯示的是偶數行
6.常用的action
1.表達式Expressions
2.控制語句Control statements :if while等
3.組合語句Compound statements :組合語句
4.輸入語句input statements
5.輸出語句outut statements :print等
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 }
awk控制語句if-else
語法:if(condition) statements [ else statements]
if(condition1) {statement1}else if(condition2) {statement2} esle{statement3}
使用場景:對awk取得的整行或某個字段做條件判斷
示例:
如果uid大于1000就顯示此行中的第1,3列,分隔符為”:“
如果uid大于1000則顯示為conmmon user,否則顯示system user,并顯示第1,3列,分隔符為”:“
說明 90分以下為very good 60-90為good,60分以下為不及格
以/dev開頭的行,分隔符為%,取第一列,然后顯示的行中默認可個為分隔符,最后一行如果大于20,則顯示第1行和最后一行
awk控制語句=====while循環
語法:while(condition){statement}
條件為”真“,進入循環;條件為”假“,退出循環
使用場景:
對一行內的多個字段注意類似處理時使用
對數組中那個的各元素逐一處理時使用
示例:
說明:文件為/etc/grub.cfg,匹配以任意數量的空格開頭后面跟Linux16的行,做while循環,初始值i=1,判斷題條件為i<NF(每行字段數),
i++自增,打印內容為每行的每個字段,以及此字符個數。默認分隔符為" "
說明:在上面的基礎上加了一個判斷條件,字段中字符分個數大于等于10,打印內容為每行的每個字段,以及此字符個數。默認分隔符為" "
awk控制語句=====do-while循環
語法:do {statement;…}while(condition)
意義:無論真假,至少執行一次循環
示例:
說明不同:
后面的i沒有爭議,那么i++和++i的卻別就在于,先后順序,
第一個是先顯示i,然后才自增賦值的,所以值為
第二個是先自增賦值,然后才顯示i的,所以值為1
awk控制語句===for循環
語法:for(expr1;expr2;expr3){statement;…}
常見用法:
for(variable assignment;condition;iteration process){for-body}
特殊用法:能夠遍歷數組中的元素;
語法: :for(var in array) {for-body}
示例:
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
性能比較:
time (awk 'BEGIN{total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
time(total=0;for i in {1..1000000};do total=$(($total+i));done;echo $total)
time(for ((i=0;i<=1000000;i++));do let total+=i;done;echo $total)
結果很顯然是awk運算最快,想想也知道了,這章博客主要內容就是awk,做這個比較肯定想體現akw是有多牛逼咯
awk控制語句====>switch語句
語法:swicth(expression){case VALUE1 or /REGEXP/:statement;case VALUE2 or /REGEXP2/:statement;…;default:statement}
break和continue
示例:
break表示當i=66的時候中斷此循環,所以結果是1加到65
continue表示當i為偶數的時候終止了本輪循環,所以結果為奇數相加
break[n]
continue[n]
next:
提前結束對本行處理而直接進入下一輪處理(awk自身循環)
說明:當uid為奇數時,提前結束本行,跳過本行要處理的,
awk數值:array[index-expression]
index-expression:
1.可使用任意字符串;字符串要使用雙引號括起來
2.如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串”
若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷
示例:
awk ‘!a[$0]++’ dupfile
若要遍歷數組中的每個元素,要使用for循環
for(var in array) {for-body}
注意:var會遍歷array的每個索引
示例:
說明:統計tcp開頭的單詞中最后一字段出現次數
說明:統計第一段ip出現的次數
awk函數:
rand():返回0和1之一個隨機數
[root@localhost ~]# awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
字符串處理:
length([s]):返回指定字符串的長度
sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,并將第一個匹配的內容替換成s
echo "2008:08:08 08:08:08" | awk 'sub(/:/,“-",$1)'
gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,并全部替換為s所表示的內容
echo "2008:08:08 08:08:08" | awk ‘gsub(/:/,"",$1)'
split(s,array ,[r]):以r為分隔符,切割字符s,并將切割后的結果保存至array所表示的數組中,第一個索引值為1
第二個索引值為2…
自定義函數
格式
function name (parameter,parameter,….){
statements
return exprossion
}
示例:
#!/bin/bash function max(v1,v2) { v1>v2?var=v1:var=v2 return var } BEGIN{a=3;b=2;print max(a,b)}
1 #!/bin/bash 2 function max(v1,v2) { 3 v1>v2?var=v1:var=v2 4 return var 5 } 6 BEGIN{print max(a,b)}
awk中調用shell命令
system命令
空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk
的變量外其他的一律用“”引用起來
awk腳本
將awk程序寫成腳本,直接調用或執行
示例:
向awk腳本傳遞參數
格式:
awkfile var=value var2=value2… Inputfile
[root@localhost bin]# cat test.awk #!/bin/awk -f {if($3<=min||$3>=max)print $1,$3} [root@localhost bin]# test.awk -F: min=10 max=1000 /etc/passwd
練習
1 、 統計/etc/fstab文件中每個文件系統類型出現 的次數
awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
2、 、 統計/etc/fstab 文件中每個單詞出現的次數
[root@localhost bin]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab man 1 and/or 1 /mnt 1 maintained 1 xfs 4 14:09:19 1 UUID=b39702a5-31f8-4fca-96cc-3389a0a58059 1 Accessible 1 # 7 are 1 defaults 5 blkid(8) 1 / 1 0 13 See 1 3 1 Mon 1 Created 1 on 1 usrquota,grpquota 1 mount(8) 1 ext4 2 acl 1 anaconda 1 fstab(5), 1 /boot 1 /testdir 1 /usr 1 UUID=bd915a87-493a-415b-8d2f-8cedaab84792 1 findfs(8), 1 2016 1 /home 1 '/dev/disk' 1 UUID=5bc0405e-cf7a-4d60-8c0c-a6daa1dd71d2 1 by 2 /etc/fstab 1 UUID=12294f2d-4b7d-4f64-a8b7-1522fe51d0b2 1 pages 1 UUID=d8150c22-3804-4d3e-bd18-8f44e93bb978 1 more 1 25 1 info 1 UUID=8d687919-88d4-4c2a-9e0b-473cd13bb785 1 swap 2 Jul 1 UUID=14efdeb1-9880-49dc-aaa0-321c4eb4816a 1 filesystems, 1 reference, 1 for 1 under 1
原創文章,作者:qiuwei,如若轉載,請注明出處:http://www.www58058.com/47950