AWK高階應用
AWK高階應用
在進行資料割接時,需要對其匯出指令碼的日誌檔案進行統計分析以便核對是否有資料沒有匯出的情況!該日誌檔案的格式都是固定的,可以使用指令碼來完成統計分析,而且指令碼很靈活小巧。
因為其複雜的語法和不明確的錯誤提示,造成awk的使用者進而遠之,awk整體上比較難掌握。Awk是一種自解釋的程式語言。而awk強大的文字處理功能正好能夠勝任該工作。如果要格式化報文或從一個大的文字檔案中抽取資料包,那麼awk可以完成這些任務。它在文字瀏覽和資料的熟練使用上效能優異。
Awk的特性網上有很多資料,大家可以參考一下。本次所運用的awk的特性有:
Awk陣列、printf修飾符、內建字串函式、awk操作符、條件操作符。
要想使用好awk,必須對awk的語法有一定的認識,否則你會被一大堆莫名其妙的錯誤所包圍。
Awk語句都是由模式和動作組成。模式的包括倆個關鍵字,BEGIN和END。BEGIN模式在awk遍歷文字前呼叫,用來列印一些頭資訊或是宣告一些全域性變數。例如:
Log.dat記錄著日誌資訊,日誌為日期-ip-手機號碼。
linux:/home/dss/dss/logs/msgs> cat log.dat
20091111-172230-665-10.168.38.63-15035198115
20091111-172230-738-10.168.38.65-13840784654
20091111-172238-571-10.168.38.63-15929933330
20091111-172238-668-10.168.38.63-13666463997
20091111-172240-262-10.168.38.68-13591931301
20091111-172242-24-10.168.38.63-15041615076
20091111-172248-427-10.168.38.63-13409199466
如果我想統計來自ip10.168.38.63的日誌有幾個,命令如下:
linux:/home/dss/dss/logs/msgs> awk -F'-' 'BEGIN {printf "%-15s %s\n","IP","LOG"printf “===============================================”}{if($4~/10.168.38.63/)printf "%-15s %s\n", $4,$0}END{}' log.dat
IP LOG
10.168.38.63 20091111-172230-665-10.168.38.63-15035198115
10.168.38.63 20091111-172238-571-10.168.38.63-15929933330
10.168.38.63 20091111-172238-668-10.168.38.63-13666463997
10.168.38.63 20091111-172242-24-10.168.38.63-15041615076
10.168.38.63 20091111-172248-427-10.168.38.63-13409199466
其中頭資訊IP和LOG在遍歷log.dat前列印!
而END模式在遍歷完檔案最後執行,可以用於資訊彙總,或列印結束日誌。
實際動作需要包含在{}之間,如果不指明,預設動作是列印所有行。
Awk的域和記錄,awk執行時,其瀏覽域標記為$1,$2… $n。這種方法稱為域標識。使用這些域標識將更容易對域進行進一步處理。$0為匹配整行,看個例子:
linux:/home/dss/dss/logs/msgs> awk -F'-' '{print $4, $5}' log.dat
10.168.38.63 15035198115
10.168.38.65 13840784654
10.168.38.63 15929933330
10.168.38.63 13666463997
10.168.38.68 13591931301
10.168.38.63 15041615076
10.168.38.63 13409199466
以上命令只列印第4列和第5列。並且域分隔符為-,預設的域分隔符為空格,使用-F引數指定域分隔符。
awk有許多內建變數用來設定環境資訊。這些變數可以被改變。下面列出一些最常使用的一些變數,並給出其基本含義。
ARGC 命令列引數個數
ARGV 命令列引數排列
ENVIRON 支援佇列中系統環境變數的使用
FILENAME awk瀏覽的檔名
FNR 瀏覽檔案的記錄數
FS 設定輸入域分隔符,等價於命令列- F選項
NF 瀏覽記錄的域個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
awk有許多強大的字串函式,這些字串函式在處理文字方面起著很重要的作用。通過這些內建字串處理函式可以很隨意的定義一些自己想要的函式。下面為awk中內建字串處理函式。
gsub (r, s) 在整個$0中用s替代r
gsub (r, s, t) 在整個t中用s替代r
index (s , t) 返回s中字串t的第一位置
length ( s ) 返回s長度
match (s , r) 測試s是否包含匹配r的字串
split (s , a , fs) 在f s上將s分成序列a
sprint (fmt , exp) 返回經f m t格式化後的e x p
sub (r, s) 用$ 0中最左邊最長的子串代替s
substr (s , p) 返回字串s中從p開始的字尾部分
substr (s , p , n) 返回字串s中從p開始長度為n的字尾部分
如下我只要使用index和substr函式就可以組合出很強大的自定義函式:
function substrmid(src, begin, end) {
startindex=index(src,begin) + length(begin)
temp=substr(src,startindex)
endindex=index(temp,end) - length(end)
return substr(src,startindex,endindex)
}
function substrbefore(src, end) {
endindex=index(src,end)-length(end)
return substr(src,0,endindex)
}
function substrafter(src, begin) {
startindex=index(src,begin) + length(begin)
return substr(src,startindex)
}
自定義函式substrbefore(src, end)是擷取src中end之前的字串,substrmid(src, begin, end)是擷取src中介於begin和end之間的字串(不包含begin和end),substrend(src, end)是擷取src中end之後的字元換,例如:
Substrmid(“2009-11-01”, “-”,”-”)返回字串11,substrbefore(“2009-11-01”, “-”)返回2009,substrafter(“11-01”, “-”)返回01,可以根據自己的需要構造一些自定義函式。
最後簡單介紹一下awk中的陣列應用。Awk是一種類似自解釋語言,其中的資料應用可以很好的完成資料統計工作。Awk中陣列使用無需提前宣告。陣列使用前,不必定義,也不必指定陣列元素個數。經常使用迴圈來訪問陣列。下面是一種迴圈型別的基本結構
For (element in array ) print array[element]
Awk的特性介紹完了,現在開始實戰了!
這個小工具的要求是這樣的,在做資料割接時,將資料庫的資料按照路由規格利用資料庫提供的批量匯出工具把資料匯出成dat檔案,需要對資料庫的日誌進行統計分析,看看每個分庫每個分表匯出多少條記錄!
SQL3104N The Export utility is beginning to export data to file
"./PISADB10/CONTACTINFO977_1_3717.dat".
中間有若干行無關緊要的內容
Number of rows exported: 24040
其中的./PISADB10/CONTACTINFO977_1_3717.dat和Number of rows exported: 24040為關鍵資訊。
PISADB10表示分庫10,CONTACTINFO977_1_3717.dat表示分表1。而Number of rows exported: 24040為匯出多少行。而日誌檔案裡有上萬行這樣的日誌,而且大概有100多個日誌,要求這個小功能能夠做到批量統計。
首先使用grep命令將相關重要資訊提取出來,以免其他資訊造成干擾。使用命令
Grep –E ‘^Number of rows exported|^".*(CONTACTINFO|DS_CLIENT_MAPPING|GROUPCONTACTMAP)\w*.dat’ db2export_1.sh.log
命令輸出格式為:
。。。
"./PISADB5/CONTACTINFO472_1_12012.dat".
Number of rows exported: 40
"./PISADB5/CONTACTINFO473_1_12033.dat".
Number of rows exported: 24040
"./PISADB5/CONTACTINFO474_1_12054.dat".
Number of rows exported: 40
"./PISADB5/CONTACTINFO475_1_12075.dat".
Number of rows exported: 40
"./PISADB5/CONTACTINFO476_1_12096.dat".
Number of rows exported: 40
以上資訊才是我想要的。將結果交給awk來處理完成,由於awk本身的機制,awk只能按行來處理檔案,一次只能處理一行,所有以上資訊處理還需要一些特殊的適配。Awk一次只讀一樣,如果該行不包含Number說明該行為分庫和分表資訊行,將其暫存起來,等到下一行Number行時,再對其進行處理。這裡可以使用awk中的條件操作符if語句來完成,{if($0!~/Number/) tmp=$0} {if($0~/Number/)print “This is a number line and it’s owner is ”tmp},其中if的條件判斷無需用()引起來,但是未避免語句錯誤最好將所有的條件判斷都用()擴起來。!~為不匹配~為匹配,//之間可以輸入正規表示式。
當行為number行時,需要將其中的關鍵數字擷取出來做彙總。
if($0!~/Number/){
num=substrafter($0,” exported: ”)
}
這樣就將num擷取出來了,剩下的就是做彙總資訊了!完整的指令碼如下:
grep -E '^Number of rows exported|^".*(CONTACTINFO|DS_CLIENT_MAPPING|GROUPCONTACTMAP)\w*.dat' db2export_1.sh.log | awk '
function substrmid(src, begin, end) {
startindex=index(src,begin) + length(begin)
temp=substr(src,startindex)
endindex=index(temp,end) - length(end)
return substr(src,startindex,endindex)
}
function substrbefore(src, end) {
endindex=index(src,end)-length(end)
return substr(src,0,endindex)
}
function substrafter(src, begin) {
startindex=index(src,begin) + length(begin)
return substr(src,startindex)
BEGIN {
flag=""
total=0
table=""
}
{
if($0!~/Number/) {
flag=$0
}
}
{
if($0~/Number/) {
print $0
num=substrafter($0,"exported: ")
partdb=substrmid(flag, "/", "/")
fromtable=substrmid(flag, "_", "_")
P[partdb]=P[partdb]+num
S[fromtable]=S[fromtable]+num
total=total+num
}
}
END {
print "Total number of export: "total
for(p in P){
print p" number of export: "P[p]
}
for(s in S){
print "parttable "s" number of export: "S[s]
}
}
相關文章
- Redis 高階應用Redis
- React 高階應用 -- 高階元件 Heigher Order ComponentReact元件
- 「Mybatis系列」Mybatis高階應用MyBatis
- LVS高階應用-會話保持會話
- ansible高階應用ansible-vault
- Docker 運維高階應用管理Docker運維
- Linux awk 中 xxxx的應用Linux
- react 高階元件的 理解和應用React元件
- Hive 高階應用開發示例(一)Hive
- C++高階應用_設計模式C++設計模式
- 向量(高階的隨機化應用)隨機
- STM32F103 高階應用(2)——中斷應用
- 基於PostGIS的高階應用(5)–PolygonSplitingGo
- WinRAR初級中級高階等應用
- 分享Python的5種高階特徵應用Python特徵
- Spring AOP高階應用與原始碼剖析Spring原始碼
- Jenkins 使用指南 之 高階應用篇Jenkins
- ArkWeb頁面跳轉與跨應用導航 - 高階應用Web
- React 高階應用 -- 錯誤邊界 Error BoundariesReactError
- 說說 vue-router 元件的高階應用Vue元件
- React 中的高階元件及其應用場景React元件
- day16-物件導向高階和應用物件
- Nuget一鍵打包上傳以及高階應用
- MACD技術的高階應用--MACD與波浪Mac
- ArkWeb高階安全模式 - 提升應用安全性Web模式
- c# 高階應用 理解擴充套件方法C#套件
- Netty高階應用及聊天室實戰Netty
- 技術進階:Kubernetes高階架構與應用狀態部署架構
- oracle學習筆記(十七) PL/SQL高階應用Oracle筆記SQL
- 高階玩法之類的裝飾器的應用
- Tomcat高階配置(應用場景總結及示例)Tomcat
- css高階應用三種方法實現多行省略CSS
- FTP-Vsftpd的高階應用:虛擬使用者FTP
- gojs 實用高階用法GoJS
- Excel高階應用教程:資料處理與資料分析Excel
- 高階函式應用 —— 柯里化與反柯里化函式
- 跟我學SpringCloud | 第十四篇:Spring Cloud Gateway高階應用SpringGCCloudGateway
- 深入 Python 資料分析:高階技術與實戰應用Python