一.Regex1.1國際字元模式比對或匹配模式的類名
[:alnum:] : 0-9,A-Z,a-z
[:alpha:] : A-Z,a-z
[:upper:] : A-Z
[:lower:] : a-z
[:digit:] : 0-9
[:space:] : 空格或tab鍵
1.2基礎Regex
^word:待尋找的字串在行首。
word$:待尋找的字串在行尾。
. :代表一定有一個任一字元的字元。
\ :逸出字元,將特殊符號的意義去除。
* :重複0個到無窮多個的前一個字元。
[list]:從字元集合的RE字元裡面找出想要選取的字元,在[]當中代表一個待尋找的字元;
例如:[afg]代表a或f或g的意思。
[n1-n2]:代表想要找出的字元範圍;
eg:[0-9]表示0到9;[a-z]代表a到z。
[^list]:找出不要的字串或範圍,即找出不含list中字串的;
eg:[^A-Z]:代表不要非大寫字母;[^t]:不要字母t。
\{n,m\}:相當於{n,m}的轉義,因{的轉義為\{,因}的轉義為\},表示連續n到m個前一個字元。
\{n\}:相當於{n},即表示重複n個前一個字元。
\{n,\}:相當於{n,},表示連續n個以上的前一個字元。
註:Regex的特殊字元與一般命令列輸入命令的“萬用字元”並不相同。在萬用字元中*表示0到無限多個字元。但在Regex中,*則是0到無窮多個前一個字元。
eg:尋找以a開頭的檔案名稱的兩種實現:
萬用字元: ls -l a*
Regex:ls -l | grep '^a.*'
1.3擴張Regex
grep預設只支援基礎Regex,如果使用擴充性運算式,可以使用grep -E,不過更建議直接使用egrep。egrep == grep -E。
+ :重複一個或一個以上的前一個RE字元。
eg:egrep -n 'go+d' a.txt
即god,good,goood,...。
? :0個或1個的前一個RE字元。
eg: egrep -n 'go?d' a.txt
即gd,god,good,...。
| :用或(or)的方式找出數個字串。
eg:egrep -n 'gd|god' a.txt
尋找含gd或good的行。
():找出‘組’字串
eg:egrep -E 'g(la|oo)d' a.txt
找出glad或good的行。
()+:多個重複的群組的判別
eg:egrep 'A(xyz)+C' a.txt
開頭為A,結尾為C,中間位1一個以上的xyz字串。
註:RE:regular expression(Regex)。
二.awk命令
2.1awk概述
互連網中對日誌分析,大多使用的是linux中的shell進行處理。此時主要使用的shell中的awk,因為awk強大的欄位處理能力。下面就對其由淺入深,最後給出執行個體進行講解。
首先給出一個很好的awk學習連結:http://www.cnblogs.com/chengmo/tag/awk/ 。
awk比較傾向於將一行分成數個“欄位”來處理,其運行模式為:
awk '條件類型1{動作1} 條件類型2{動作2}...' filename
註:awk主要是處理每一行的欄位內的資料,而預設的欄位的分隔字元為空白格鍵或tab鍵。
2.2awk入門
(1)eg: last -n 5 | awk '{print $1 "\t" $3}'
表示將登陸者的資料取出來,僅取前5行。其中$1表示當前行的第一個資料;$3表示當前行的第三個資料。
(2)awk是如何知道這個資料有幾行幾列呢?這需要下面的內建變數進行幫忙:
NF:每一行($0)的欄位總數;NR:目前awk所處理的是第幾行;FS:目前的分隔字元,預設為空白格鍵。
eg:在/etc/passwd當中是以冒號來作為欄位分隔符號的,該檔案第一個欄位為帳號,第3個欄位為UID,那下面要查詢第3列小於10以下的資料,並且僅列出第一列與第三列,可以如下做:
cat /etc/passwd | awk ‘BEGIN{FS=":"} $3<10{print $1 "\t" $3}’
輸出如下:
root 0
bin 1
註:BEGIN:讓使用者指定在第一條輸入記錄被處理之前所發生的動作,通常可在這裡設定全域變數。END:讓使用者在最後一條輸入記錄被讀取之後發生的動作。
(3)有如下的薪資表pay.txt,內容如下:
Name 1st 2st 3st
Sean 23000 24000 25000
Zhao 21000 20000 23000
Bird2 43000 42000 41000
那如何格式化輸出,並能計算每個人的總額呢?
如下考慮:第一行不需要加總,只是說明(NR==1);第二行以後,有加總(NR>=2)。
命令如下:
cat pay.txt | awk '{
if(NR==1)
printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}
NR>=2{
total=$2+$3+$4
printf "%10d %10d %10d %10d %10.2f\n ",$1,$2,$3,$4,total }'
也可以這樣:
cat pay.txt | awk 'NR==1{
printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total"}
NR>=2{
total=$2+$3+$4
printf "%10d %10d %10d %10d %10.2f\n ",$1,$2,$3,$4,total }'
(4)如何查看一個檔案的最後5行:tail -n 5 a.txt
如何查看有一個檔案的前5行:head -n 5 a.txt
列印檔案的行數:awk ‘END{print NR}’ data.txt
(5)如何查看一個檔案夾下檔案的個數
ls -l | awk 'END{print NR}'
註:表示處理完最後一行的時候,輸出當前的NR,即檔案的總行數。
(6)每4行轉換成一行
awk '{if(NR%4==0){print $0}else{printf "%s",$0}}' a.xml
2.3awk的實際應用
現在給出日誌資料,只給出幾行,如下所示:
23:59:59 bj other other1 detail 1 0 8178526912798594496654
23:59:59 ly fang fang1 list 34 2 7564641773641447038883
23:59:59 bj fang fang1 detail 1 0 4062479590911058005479
23:59:59 bj fang fang1 detail 1 0 7311067232020513225874
(1)awk統計日誌中的pv和uv
pv表示頁面的訪問量,即重新整理一次算一次訪問。uv表示訪客數,即訪問這個頁面的使用者數。
下面實現統計該日誌中的所有pv和uv,同時統計每一個大類(第三列資料)的pv和uv,shell如下所示:
#!/bin/shif [ $# -lt 1 ]; then echo "Usage:" echo " $0 [filename]" exit 1fiif [ "$1" == "-h" ]; then echo "Usage: $0 [filename]" exit 1fiawk -F"\t" '{ total[$8] ++; uvlist[$3"#"$8] ++; if($5 == "detail") { detailpv ++; pvlist[$3] ++; }}END{ print "total\t"detailpv"\t"length(total) for(k in uvlist) { split(k, c, "#"); cate[c[1]] ++; } for(k in pvlist) { print k"\t"pvlist[k]"\t"cate[k]; }}' $1
運行結果如下:
(2)awk從日誌中統計線上率
這裡統計是根據第二列(城市)和第三列(大類)進行統計的。shell如下:
#!/bin/shif [ $# -lt 1 ]; then echo "Usage:" echo " $0 [filename]" exit 1fiif [ "$1" == "-h" ]; then echo "Usage: $0 [filename]" exit 1ficat $1 | awk -F"\t" '$5 == "list"{ if($2 != "bj" && $2 !="sh" && $2 != "gz" && $2 != "sz") next; citycategory = $2"_"$3; citymajor = $2"_"$4; if($3 == "fang") { ctotal[citymajor] += $6; conline[citymajor] += $7; } ctotal[citycategory] += $6; conline[citycategory] += $7; listall += $6; listonlineall += $7;}$5 == "detail"{ if($2 != "bj" && $2 !="sh" && $2 != "gz" && $2 != "sz") next; citycategory = $2"_"$3; citymajor = $2"_"$4; if($3 == "fang") { dctotal[citymajor] += $6; dconline[citymajor] += $7; } dctotal[citycategory] += $6; dconline[citycategory] += $7; detailall += $6; detailonlineall += $7;}END{ #按城市和大類一起統計 cslen=asorti(ctotal,clA); print "<table border=\"1\"><caption align=\"top\">使用者線上率統計</caption><tr><td>城市</td><td>類別</td><td>列表頁總人數</td><td>列表頁線上率</td><td>詳情頁總人數</td><td>詳情頁線上率</td></tr>"; for(i=1; i <= cslen; i ++) { split(clA[i], arr, "_"); dc = dct = "-"; if(clA[i] in dctotal) { dct = dctotal[clA[i]]; dc = dconline[clA[i]]/dct; } printf("<tr><td>%s</td><td>%s</td><td>%d</td><td>%.2f%%</td><td>%d</td><td>%.2f%%</td></tr>", arr[1], arr[2], ctotal[clA[i]], conline[clA[i]]*100/ctotal[clA[i]], dct, dc *100); } print "</table><br/><br/>";}'
三.grep命令3.1grep概述
grep:進行字元的對比,將符合要求的字元列印出來。是以Regex搜尋文本,並列印匹配行。grep是以整行為單位來進行資料的選取的。
其格式: grep [option] 'Regex' 檔案名稱
option: -n表示列印出時,顯示行號;
-v表示反向選擇,即不要符合Regex的行;
-A:後可加數字,為after意思,除了該行外,後續的n行也可列出。eg:-A3
-B:為before,除了該行外,前面的n行也可列出。
3.2grep入門
(1)尋找特定字串
grep -n 'the' a.txt :尋找含the的行,並顯示行號
grep -vn 'the' a.txt:尋找不含the的行,並顯示行號
grep -in ‘the’ a.txt:忽略the的大小寫,尋找含the的行,即the、The、tHe......
(2)尋找字元集合,利用[]
grep -n 't[ae]st' a.txt :尋找含tast或test的行
grep -n '[^g]oo' a.txt :oo前面不要出現g
grep -n '[^a-z]oo' a.txt :不想oo前面含小寫字母,等價於grep -n '[^[:lower:]]oo' a.txt
(3)行首與行尾字元^$
(a)grep -n '^[^a-zA-Z]' a.txt :不要以字母開頭的行
等價於grep -n '^[^[:alpha:]]' a.txt
註:^在[]之外表示定位在行首。^在[]之內表示“反向選擇”。
(b)grep -n '\.$' a.txt:以.結束的行。因.表示任一字元,所以是特殊符號,需要轉義。
(c)grep -n '^$' a.txt:找出哪些行是空行。
(d)grep -v '^$' a.txt | grep -v '^#':不要空行和以“#”開頭的行。
(4)任意一個字元.與重複字元*
grep -n 'g..g' a.txt :表示g__g的字元
grep -n 'g*g' a.txt:g*表示一個Null 字元或一個以上的g,再加上後面的g。
grep -n ‘g.*g’ a.txt:表示g開頭與g結尾。*表示0個或任意多個字元。
(5)限定連續RE字元的範圍
因{}在shell中是有特殊意義的,因此我們必須用逸出字元\來讓它失去特殊意義才行的。
grep -n 'go\{2,\}g' a.txt:表示含2個以上的o。即good、goood、....
四.sed命令4.1sed概述
sed常用於一整行的處理,主要對檔案中的行進行操作。
其格式為:sed [-nefr] [動作]
動作說明:[定址] function
定址方式如下:
(1)n1[,n2]:表示n1到n2之間進行動作。eg:10,20[動作行為]
(2)/pattern/:模式(Regex)pattern指定的行
(3)/pattern/,/pattern/:2個模式(Regex)之間的行進行動作
(4)/pattern/,x:模式+行(在給定行號上查詢模式)
(5)x,y/pattern/:通過行號和模式比對行
(6)x,y!:不包含指定行號
(7)$:表示最後一行
註:範圍可通過數值,Regex或者二者結合的方式確定。
fuction(即動作)如下:
(1)a:append(新增),在目前定址行的下一行插入字串
(2)c:change(替換),替換當前定址到的行為字串
(3)d:delete(刪除),刪除當前定址的行
(4)i:insert(插入),在定址行的上一行插入字串
(5)p:print(列印),列印當前定址行的資料
(6)s:substitute(替換),其格式為:'s/要替換的字串/新的字串/g'
註:a、c、i動作之後,可以用空格或“\”隔開字串
4.2sed入門
(1)以行為單位的新增功能
註:新增操作,結果到標準輸出,不能被編輯,必須存到另一檔案中。
在匹配行的下一行插入一行:
sed '/dreamb/a\appended line' a.txt :表示將含“dreamb”的匹配行後插入一行“appended line”
或 sed '/dreamb/a append line' a.txt
cat /etc/passwd | sed '2a drink tea':表示在第二行後追加一行“drink tea”
如果想儲存修改,一般是重新導向到另外的一個檔案。
sed '/five/i four' a.txt > result.txt:表示含“five”的匹配行的上一行插入一行“four”
如果想直接修改源檔案,可以用下面的命令:
sed -i '/five/i four' a.txt
(2)修改文本
sed '3c\changed line' a.txt :表示在第三行替換為“changed line”
等價於sed '3c changed line' a.txt
(2)刪除文本
sed '1,3d' a.txt:刪除1到3行
sed '/dreamd/d' a.txt:刪除含“dreamd”的行
sed -n '/Begin/,/End/d' a.txt | more:刪除兩個匹配行之間的資料
sed '$d' a.txt:刪除最後一行
sed '/^th/d' a.txt:刪除以th開頭的行
(3)替換
替換格式:sed '[address[,address]] s/pattern_find/replacement_pattern/[g,p,w,n]' filename
其中,g表示對模式空間中的所有情況進行替換,預設只替換首次出現的模式。
sed '1,2 s/d$/&dd' a.txt:將1-2行中的所有以d結尾的行,都附加上一個dd
sed '/first/ s/st/ST/' a.txt:將含有“first”的行中st換成大寫ST
cat /etc/man.config | grep 'MAN' | sed 's/#.*$'//g':表示刪除掉“#”批註之後的資料
(4)轉換檔
通常用於大小寫轉換
文法為:y/abc/xyz/
sed 'y/five/six1' a.txt:將five轉換成six1
(5)顯示匹配行
sed -n '5,7p' a.txt:顯示a.txt中的5-7行
等價於head -n 7 | tail -n 3:即前7行中的後3行