標籤:shell awk Regex
awk編程
awk是一種程式設計語言。gawk、是最新版本,當前的linux版本用的都是gawk
awk是gawk的軟連結
awk工作原理
BEGIN #在未讀取檔案行之前執行
主輸入迴圈 (main input loop),反覆執行,直到終止條件觸發
END #在讀取檔案行完畢後執行
awk的三種調用方法
1、在shell命令列輸入命令調用awk
#awk [-f 域分隔字元] ‘awk cmd‘ file
2、在awk程式段插入指令檔,然後通過awk命令調用他
#awk -f ‘awk.sh‘ file
3、直接調用awk指令碼
#./awk file
=====================================================
awk模式比對
任何awk語句都由模式(pattern)和動作(action)組成
模式是一組用於測試輸入行是否需要執行動作的規則(模式決定動作何時觸發和觸發事件)
動作是包含語句、函數和運算式的執行過程 (執行對輸入行的處理)
在test檔案中一旦有空行,則列印出來"This is a empty line!!!"
#awk ‘/^$/{print "This is a empty line!!!"}‘ test
=====================================================
記錄和域
awk將每個輸入檔案行定義為記錄,行中的每個字串定義為域,分隔域的符號叫做域分隔字元
vim student
Li Hao njue 025-83481010
Zhang Ju nju 025-83466534
Wang Bin seu 025-83494883
Zhu Lin njupt 025-83680010
按順序列印出student檔案中的2、1、4、3域
#awk ‘{print $2,$1,$4,$3}‘ student
列印出student中所有的域
#awk ‘{print $0}‘ student
根據運算運算式列出第三個域的值
#awk ‘BEGIN {one=1;two=2}{print $(one+two)}‘ student
以tab鍵位分隔字元列印出student檔案中第三個域
#awk ‘BEGIN {FS="\t"} {print $3}‘ student
Li Hao,njue,025-83481010
Zhang Ju,nju,025-83466534
Wang Bin,seu,025-83494883
Zhu Lin,njupt,025-83680010
以逗號為域分隔字元列印出所有的域的內容
#awk ‘BEGIN {FS=","} {print $0}‘ student
以逗號為域分隔字元列印出1、3域的內容
#awk ‘BEGIN {FS=","} {print $1,$3}‘ student
abc d #中間兩個tab
abc d #中間一個tab
列印出第一個域和d(兩種方式)
#awk ‘BEGIN {FS="\t\t"} {print $1,$2}‘ xx
#awk ‘BEGIN {FS="\t"} {print $1,$3}‘ xx
列印出第一個域和上面的d
#awk ‘BEGIN {FS="\t"} {print $1,$2}‘ xx
===============================================================
關係運算子
< #小於
> #大於
<= #小於等於
>= #大於等於
== #等於
!= #不等於
~ #匹配Regex
!~ #不匹配Regex
在/etc/passwd檔案中列印出第一個域匹配於root的內容
#awk ‘BEGIN {FS=":"} $1~/root/‘ /etc/passwd
在/etc/passwd檔案中列印出全部域匹配於root的內容
#awk ‘BEGIN {FS=":"} $0~/root/‘ /etc/passwd
在/etc/passwd檔案中列印出全部域中不匹配nologin的內容
#awk ‘BEGIN {FS=":"} $0!~/nologin/‘ /etc/passwd
在/etc/passwd檔案中判斷,如果UID小於GID,那麼輸出所有匹配的值
#awk ‘BEGIN {FS=":"} {if($3<$4) print $0}‘ /etc/passwd
在/etc/passwd檔案中判斷,如果UID大於等於GID,那麼輸出所有匹配的值
#awk ‘BEGIN {FS=":"} {if($3>=$4) print $0}‘ /etc/passwd
===============================================================
布林運算子
|| #邏輯或
&& #邏輯與
! #邏輯非
列印出/etc/passwd檔案中UID等於10或者GID等於10的行
#awk ‘BEGIN {FS=":"} {if($3==10||$4==10) print $0}‘ /etc/passwd
列印出/etc/passwd檔案中UID等於GID,並且登入shell都相同的匹配資訊
#awk ‘BEGIN {FS=":"} {OFS=":"} {if($3==$4&&$7="/sbin/nologin") print $0}‘ /etc/passwd
列印出/etc/passwd檔案中UID匹配於10或GID匹配於10的匹配資訊
#awk ‘BEGIN {FS=":"} {if($3~10||$4~10) print $0}‘ /etc/passwd
================================================================
運算式 awk運算式用於儲存、操作和擷取資料,一個awk運算式可由數值,字元常量,變數,操作符,函數和正則組成
+ #加
- #減
* #乘
/ #除
% #模
^或** #乘方
++x #在返回x值之前,x變數加1
x++ #在返回x值之後,x變數加1
使用x+=1來列出檔案test中的空行的行數
#awk ‘/^$/ {print x+=1}‘ test
第1行為0,然後遞迴+1列出test檔案中的空行行數
#awk ‘/^$/{print x++}‘ test
第1行為1,然後遞迴+1列出test檔案中的空行行數
#awk ‘/^$/{print ++x}‘ test
執行個體
Li hao,njue,025-83481010,85,92,78,94,88
Zhang Ju,nju ,025-83466534,89,90,75,90,86
Wang Bin, seu,025-83494883,84,88,80,92,84
Zhu Lin,njupt,025-83680010,98,78,81,87,76
求出檔案student檔案中學生的平均值
#awk ‘BEGIN {FS=","} {total=$4+$5+$6+$7+$8} {avg=total/5} {print $1,avg}‘ student
================================================================
系統變數:awk定義了很多內建變數用於設定環境變數資訊,我們稱它為系統變數,這些系統變數分為兩種
1、用於改變awk的預設值,如域分隔字元
2、用於定義系統值,在處理檔案時可以讀取這些系統值,如記錄中域數量,目前記錄數,當前檔案名稱,awk動態改變第二種系統變數的值
awk環境變數及其意義
#n #目前記錄的第n個域,域間由FS分割
#0 #記錄的所有域
ARGC #命令列參數的數量
ARGIND #命令列中當前檔案的位置(以0開始標號)
ARGV #命令列參數的數組
CONVFMT #數字轉換格式
ENVIRON #環境變數關聯陣列
ERRNO #最後一個系統錯誤的描述
FILEDWIDTHS #欄位寬度列表,以空格鍵分隔
FILENAME #當前檔案名稱
FNR #瀏覽檔案的記錄數
FS #欄位分隔符號,預設是空格鍵
IGONRECASE #布爾變數,如果為真,則進行忽略大小寫匹配
NF #目前記錄中的域數量
NR #目前記錄數
OFMT #數位輸出格式
OFS #輸出域分隔字元,預設是空格鍵
ORS #輸出記錄分隔字元,預設是分行符號
RLENGTH #由match函數所匹配的字串長度
RS #記錄分隔字元,預設是空格鍵
RSTART #由match函數所匹配的字串的第1個位置
SUBSEP #數組下標分隔字元,預設值是\034
輸出檔案student,並在最前面加入 目前記錄數,目前記錄中域數量,在檔案底部輸出檔案名
#awk ‘BEGIN {FS=","} {print NR,NF,$0} END {print FILENAME}‘ student
====================================================================
格式化輸出 awk借鑒了C語言的文法,定義了printf輸出語句,規定輸出的格式
printf (格式控制符,參數)
printf語句包含兩部分
1、格式控制符,都是以%符號開始,用以描述格式規範
2、參數列表,比如變數名列表,與格式控制符相對應,是輸出的對象、
printf修飾符及其意義
- #靠左對齊
width #域的步長
.prec #小數點右邊的位元
printf格式符及其意義
%c #ASCII字元
%d #整型數
%e #浮點數,科學記號標記法
%f #浮點數
%o #八進位
%s #字串
%x #十六進位數
在student中列印出字串$2和整型數$8,並且$2之後tab,$8之後換行
#awk ‘BEGIN {FS=","} {printf("%s\t%d\n",$2,$8)}‘ student
將數字65轉換為ASCII碼
#awk ‘BEGIN {printf("%c\n",65)}‘
將2014轉換為浮點數,預設小數位六位
#awk ‘BEGIN {printf("%f\n",2014)}‘
列印出student檔案中的第一個域和第三個域,並且第一個域的字串和第三個域的字串相差15個空格
#awk ‘BEGIN {FS=","} {printf("%-15s\t%s\n",$1,$3)}‘ student
列印出student檔案中的第一個域和第三個域,並且在行首加入第一個域的注釋Name,第三個域的注釋Phonenumber
#awk ‘BEGIN {FS=",";print "Name\t\tPhonenumber"} {printf("%-16s%s\n",$1,$3)}‘ student
列印出浮點數控制在10為,小數點後保留三位的數
#awk ‘BEGIN {printf("%10.3f\n",20141126)}‘ #如果數不滿10位,則會按空格補齊
2011111.000 滿10位
201.000 不滿10位
===================================================================
內建字串函數 awk提供了強大的內建字串函數,用於實現文本的字串替換、尋找以及分隔等功能
awk字串函數及其意義
gsub(r,s) #在輸入檔案中用s替換r
gsub(r,s,t) #在t中用s替換r
index(s,t) #返回s中字串第一個t的位置
length(s) #返回s的長度
match(s,t) #測試s是否包含匹配t的字串
split(r,s,t) #在t上將r分成序列s
sub(r,t,s) #將t中第1次出現的r替換為s
substr(r,s) #返回字串r中從s開始的尾碼部分
substr(r,s,t) #返回字串r中從s開始長度為t的尾碼部分
在passwd中把第一個域的root替換為"My name is root",並輸出為:格式列印出來
#awk ‘BEGIN {FS=":";OFS=":"} gsub(/root/,"my name is root",$1) {print $0}‘ /etc/passwd
在passwd中把所有域的root替換為"My name is root",並輸出為:格式列印出來
#awk ‘BEGIN {FS=":";OFS=":"} gsub(/root/,"My name is root") {print $0}‘ /etc/passwd
列印出abcdefg字串中f出現的首位置
#awk ‘BEGIN {print index("abcdefg","f")}‘
列印出"This is a httpd server script"這串字串的長度
#awk ‘BEGIN {print length("This is a httpd server script")}‘
測試"This is a httpd server script!!!"這串字串中!的首位置
#awk ‘BEGIN {print match("This is a httpd server sctipt!!!","!")}‘
測試"This is a httpd server sctipt!!!"這串字串中C的首位置(忽略大小寫)
#awk ‘BEGIN {IGNORECASE=1;print match("This is a httpd server sctipt!!!",/C/)}‘
將字串"This script is a httpd server script!!!"中第一個出現的sctipt替換為SCRIPT
#awk ‘BEGIN {file="This script is a httpd server script!!!";sub(/script/,"SCRIPT",file);printf("%s\n",file)}‘
將student文本中第一個域匹配Li行中的第一個出現的10替換為99
#awk ‘BEGIN {FS=","} {$1~Li sub(/10/,"99",$0);print $0}‘ student
返回file檔案中從第5個字元開始的尾碼部分 file="This script is a httpd server script!!!"
#awk ‘BEGIN {file="This script is a httpd server script!!!";print substr(file,6)}‘
返回file檔案中從第6個字元開始長度為9的尾碼部分
#awk ‘BEGIN {file="This script is a httpd server script!!!";print substr(file,6,9)}‘
在student檔案記錄首部插入記錄行號和域數,並且使用分隔字元.進行分隔列印
#awk ‘BEGIN {FS=","} {print NR,NF,$0}‘ OFS="." student
Shell編程之---awk命令詳解