shell 字符串的處理(截取,連接,匹配,替換,翻轉)
http://www.ahlinux.com/shell/5761.html
本節分享下,shell字符串處理的內容,包括:截取,連接,匹配,替換,翻轉等。
1,字符串的截取
方法一:
代碼示例:
echo $a|awk ’{print substr( ,1,8)}’
substr是awk中的一個子函數,對第一個參數的進行截取,從第一個字符開始,共截取8個字符,如果不夠就從第二個字符中補充
方法二
代碼示例:
echo $a|cut -b2-8
cut:對標准輸入的字符串進行處理
cut -bn-m:以byte為單位,從第n個byte開始,取m個
cut -bn,m:以byte為單位,截取第n,m個byte
cut -b-n,m:以byte為單位,截取1-n,和第m個
-c:以charactor為單位
-d:指定分隔符,默認為tab
-s:使標准輸入中沒有delimeter
cut -f1:截取第1個域
方法三
a=123456
echo $
方法四
使用sed截取字符串的最后兩位
代碼示例:
echo $test |sed ’s//(.*/)/(../)$//’
截取字符串的前2位
代碼示例:
echo $test |sed ’s/^/(../)/(.*/)//’
2,字符串的比較
好像沒有什么可以比較的
3,字符串的連接
$a$b
或者
$string
4,字符串的翻轉
方法一:
使用rev命令
方法二:
編寫腳本實現
代碼示例:
#!/usr/bin/awk -f
{
revline = ""
for (i=1;i<=length;i++)
{
revline = substr(,i,1) revline
}
}
END{print revline}
5,字符串的匹配
grep
egrep
fgrep
6,字符串的排序
sort
7,字符串的替換
bash中:
代碼示例:
%x=abcdabcd
%echo $ # 只替換一個
bbcdabcd
%echo $ # 替換所有
bbcdbbcd
sh中:
??
如何替換/
使用sed
替換所有匹配
代碼示例:
echo $test |sed ’s/xx/yy’
替換單個匹配
??
8,得到字符串的長度:
bash當中
$
或者
expr "$VAR" : ’.*’
9,判斷字符串是否為數字
10,得到字符串中某個字符的重復次數
代碼示例:
echo $a |tr "x" "/n" |wc -l
得到的結果需要減去1
或者
代碼示例:
echo $a |awk -F"x" ’{print NF-1}’
11,得到字符串中某個string的重復次數
12,將一批文件中的所有string替換
代碼示例:
for i in file_list
do
vi $i <<-!
:g/xxxx/s//XXXX/g
:wq
!
done
13,如何將字符串內每兩個字符中間插入一個字符
使用sed
代碼示例:
echo $test |sed ’s/../&[insert char]/g’
======================================================================================================================================
日志分析查看——grep,sed,sort,awk運用
http://blog.csdn.net/teamlet/article/details/38046409
概述
我們日常應用中都離不開日志。可以說日志是我們在排查問題的一個重要依據。但是日志並不是寫了就好了,當你想查看日志的時候,你會發現線上日志堆積的長度已經超越了你一行行瀏覽的耐性的極限了。於是,很有必要通過一些手段來高效地輔助你來快速的從日志中找到你要找的問題。本文通過一個從項目中衍生出來的例子從查找日志,篩選日志和統計日志3個方面層層遞進來簡述日志文件查看中一些有用的手段。(注:在linux環境下)
目錄
例子背景:
后台跑一個定時任務,對指定時間段的訂單數據表中的每一條記錄進行以此任務處理。在日志中輸出:
1.訂單id
2.訂單處理狀態
3.日志類別
准備工具:sort, tail, less, uniqu,grep,sed,awk
示例日志:demo.log
- 2011-08-23 19:57:00,610 [] INFO bo.CommodityCerOrderBO - =====>屬性訂正任務執行開始|每頁讀取100條數據
- 2011-08-23 19:57:05,012 [] INFO bo.CommodityCerOrderBO - 當前正在處理頁數:1
- 2011-08-23 19:57:30,688 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids不含0跳過
- 2011-08-23 19:57:30,709 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100104
- 2011-08-23 19:57:31,721 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100105
- 2011-08-23 19:57:32,727 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100107
- 2011-08-23 19:57:32,782 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids成功保存為0|100104|0|100105|100107
- 2011-08-23 19:57:32,782 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:attr_ids不含0跳過
- 2011-08-23 19:57:32,805 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100104
- 2011-08-23 19:57:33,828 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100107
- 2011-08-23 19:57:33,838 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:46
- 2011-08-23 19:57:34,850 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100106
- 2011-08-23 19:57:35,860 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100105
- 2011-08-23 19:57:36,871 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
- 2011-08-23 19:57:36,884 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
- 2011-08-23 19:57:36,891 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10226,status:attr_ids成功保存為6|100104|0|0|100107|46|100106|100105|3|3
- 2011-08-23 19:57:36,891 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:attr_ids不含0跳過
- 2011-08-23 19:57:36,928 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
- 2011-08-23 19:57:36,942 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100104
- 2011-08-23 19:57:36,955 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100105
- 2011-08-23 19:57:36,969 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100107
- 2011-08-23 19:57:36,980 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:46
- 2011-08-23 19:57:36,992 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100106
- 2011-08-23 19:57:37,011 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10222,status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
0.一些最基礎的日志查看命令
最簡單的日志查看命令就是瀏覽日志文件了,一般會從有限瀏覽文件末尾的
- tail -400f demo.log #監控最后400行日志文件的變化 等價與 tail -n 400 -f (-f參數是實時)
- less demo.log #查看日志文件,支持上下滾屏,查找功能
- uniq -c demo.log #標記該行重復的數量,不重復值為1
以上命令具體使用詳見本機man手冊
1.查找關鍵日志記錄 grep
瀏覽了日志文件后你會發現,日志文件成千上萬行,怎么能找到我要找的內容呢。這時候,就可已用grep來進行日志的關鍵行提取了。
grep 簡單使用
規則:grep [選項]...模式 [文件]... (模式是正則表達式)
例子1:
- grep 'INFO' demo.log #在文件demo.log中查找所有包行INFO的行
輸出:
2011-08-23 19:57:00,610 [] INFO bo.CommodityCerOrderBO - =====>屬性訂正任務執行開始|每頁讀取100條數據
2011-08-23 19:57:05,012 [] INFO bo.CommodityCerOrderBO - 當前正在處理頁數:1
2011-08-23 19:57:30,688 [] INFO bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:attr_ids不含0跳過
...(略)
例子2:
- grep -o 'order-fix.curr_id:[0−9]\+' demo.log #-o選項只提取order-fix.curr_id:xxx的內容(而不是一整行),並輸出到屏幕上
輸出:
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10117
order-fix.curr_id:10226
...(略)
例子3:
- grep -c 'ERROR' demo.log #輸出文件demo.log中查找所有包行ERROR的行的數量
輸出:17
例子4:
- grep -v 'ERROR' demo.log #查找不含"ERROR"的行
輸出:(功能和grep 'INFO' demo.log 命令一樣,輸出略)
grep 用法小結(轉自網絡圖片):請點擊直接查看大圖
詳細用法請man之
2.精簡日志內容 sed
從n多行的日志文件中提取到一定數量的行后,可能你還會覺得有些功能不夠,比如你每行並不需要有哪個類拋出的描述,比如你不需要日志時間,或者要把時間格式換個形式展示等等,這時候你就可以通過sed的替換命令來進行對日志文件提取具體內容了。
如果把grep比作過濾器,那sed就是個修改器了。
sed簡單用法:
- sed [-n][-e] '命令' 文件 #-n選項是默認不輸出信息,除非使用了p命令或者是s命令的p標志符;-e是表明空格后面接的是一個命令
- sed [-n] -f 腳本 文件 #這個用法是把命令寫在腳本里
»'命令'的格式: [地址1[,地址2]][!] 指令 [參數]
» 地址的格式:用行號標識(1 表明匹配第一行),或者用正則表達式匹配('^INFO'表明該地址匹配以INFO打頭的行)
» 指令的例子:p打印指令,s替換指令,d刪除指令等等(以下表格摘自abs的sed小冊子):
操作符 | 名字 | 效果 |
---|---|---|
[地址范圍]/p |
打印 | 打印[指定的地址范圍] |
[地址范圍]/d |
刪除 | 刪除[指定的地址范圍] |
s/pattern1/pattern2/ |
替換 | 將指定行中, 將第一個匹配到的pattern1, 替換為pattern2. |
[地址范圍]/s/pattern1/pattern2/ |
替換 | 在地址范圍指定的每一行中, 將第一個匹配到的pattern1, 替換為pattern2. |
[地址范圍]/y/pattern1/pattern2/ |
transform | 在地址范圍指定的每一行中, 將pattern1中的每個匹配到pattern2的字符都使用pattern2的相應字符作替換. (等價於tr命令) |
g |
全局 | 在每個匹配的輸入行中, 將每個模式匹配都作相應的操作. (譯者注: 不只局限於第一個匹配) |
小結:sed就是遍歷對於輸入文件的每一行,如果該行匹配地址1,地址2的范圍之內,那么就對這一行執行命令。
例1:(摘自abs的sed小冊子)
8d |
刪除輸入的第8行. |
/^$/d |
刪除所有空行. |
1,/^$/d |
從輸入的開頭一直刪除到第1個空行(第一個空行也刪除掉). |
/Jones/p |
只打印那些包含"Jones"的行(使用-n選項). |
s/Windows/Linux/ |
在每個輸入行中, 將第一個出現的"Windows"實例替換為"Linux". |
s/BSOD/stability/g |
在每個輸入行中, 將所有"BSOD"都替換為"stability". |
s/ *$// |
刪除掉每行結尾的所有空格. |
s/00*/0/g |
將所有連續出現的0都壓縮成單個的0. |
/GUI/d |
刪除掉所有包含"GUI"的行. |
s/GUI//g |
將所有"GUI"都刪除掉, 並保持剩余部分的完整性. |
看完基本用法,讓我們結合demo.log來具體應用下:
例2:輸出demo.log中的某個日期中的ERROR的行
來具體應用下:
- sed -n '/^2011-08-23.*ERROR/p' demolog.log
輸出:
2011-08-23 19:57:30,709 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100104
2011-08-23 19:57:31,721 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100105
2011-08-23 19:57:32,727 [] ERROR bo.CommodityCerOrderBO - order-fix.curr_id:10117,status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100107
例3:提取demo.log中的日期,日志級別,訂單id和狀態。
- sed -f demo.sed2 demo.log
- #n #這一行用法和命令中的-n一樣意思,就是默認不輸出
- #demo.sed2
- #下面的一行是替換指令,就是把19位長的日期和INFO/ERROR,id,和后面的一截提取出來,然后用@分割符把這4個字段重新按順序組合
- s/^[−0−9]{19}.*INFO∥ERROR .*order-fix.curr_id:[0−9]\+,.∗$/\1@\3@\2@\4/p
輸出:
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:30@10117@ERROR@status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100104
2011-08-23 19:57:31@10117@ERROR@status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100105
2011-08-23 19:57:32@10117@ERROR@status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100107
2011-08-23 19:57:32@10117@INFO@status:attr_ids成功保存為0|100104|0|100105|100107
...略
sed詳細用法可以參考《sed 與 awk》(第二版), 或者man之
或者點擊下面這個參考鏈接http://www.reddragonfly.org/abscn/x17814.html
3.對記錄進行排序 sort
經過了日志文件的精煉后,我們可能不想對日志進行時間排序,這時候我們就可以用sort進行排序。
基本使用
sort [options] [file...]
對於demo.log,經過了上面的sed提取后,我希望先用id進行排序,然后再用日志級別倒序進行排序,最后才是日期排序
- #排序功能 -t表示用@作為分割符,-k表示用分割出來的第幾個域排序(不要漏掉后面的,2/,3/,1,詳細意思看下面的參考鏈接,這里不做詳述)
- sed -f test.sed demolog.log | sort -t@ -k2,2n -k3,3r -k1,1 #n為按數字排序,r為倒序
輸出:
2011-08-23 19:57:30@10117@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:32@10117@INFO@status:attr_ids成功保存為0|100104|0|100105|100107
2011-08-23 19:57:30@10117@ERROR@status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100104
2011-08-23 19:57:31@10117@ERROR@status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100105
2011-08-23 19:57:32@10117@ERROR@status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100107
2011-08-23 19:57:36@10222@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100104
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100105
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100106
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100107
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
2011-08-23 19:57:36@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:46
2011-08-23 19:57:37@10222@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
2011-08-23 19:57:32@10226@INFO@status:attr_ids不含0跳過
2011-08-23 19:57:36@10226@INFO@status:attr_ids成功保存為6|100104|0|0|100107|46|100106|100105|3|3
2011-08-23 19:57:32@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100104
2011-08-23 19:57:33@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100107
2011-08-23 19:57:33@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:46
2011-08-23 19:57:34@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100106
2011-08-23 19:57:35@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100105
2011-08-23 19:57:36@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
2011-08-23 19:57:36@10226@ERROR@status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:3
詳盡手冊http://ss64.com/bash/sort.html
4.統計日志相關記錄數 awk
現在日志已經比較清晰了,但是如果我想對不同日志進行統計怎么辦,比如我要統計所有ERROR的日志記錄書,或者要統計每個訂單有多少個ERROR?這就需要我們的awk幫忙了。
awk簡單使用:
- awk [-v 變量名=變量值] [-Fre] [--] '模式 { 語句 }' 變量名=變量值 文件名
- awk [-v 變量名=變量值] [-Fre] -f 腳本文件 [--] 變量名=變量值 文件名
和sed一樣,awk也支持2中方式調用,一種是把awk腳本直接在命令行寫入,第二種是把awk寫在文件中在命令行中調用。
awk處理方式也與sed類似,對文件中的每一個輸入行進行處理,每個處理首先判斷是否是模式中匹配的行,是的話就具體執行相應的語句。
不同的是,awk側重與對每一行的列進行處理,並且,awk腳本和c語言類似也擁有變量,條件判斷,循環等復雜語句,所以這里只能簡單介紹一下基本應用,詳細的請查看后面給出的相關鏈接。
而且,awk在處理所有行前和處理完行后各有BEGIN和END語句做預處理和后置處理。
例子1:打印日志中的第2,3列
- awk 'BEGIN{FS="@"} {print $2,$3}' demo.log_after_sort #BEGIN中預處理的是,把@號作為行的列分割符,把分割后的行的第2,3列輸出
輸出:(對於從sort得出的結果作為輸入)
10117 INFO
10117 INFO
10117 ERROR
10117 ERROR
10117 ERROR
10222 INFO
...略
例子2. 統計日志中INFO,ERROR出現的總數,以及總記錄數
- #下面的例子是作為命令行輸入的,利用單引號作為換行標記,這樣就不用另外把腳本寫進文件調用了
- awk '
- BEGIN {
- FS="@"
- }
- {
- if ($3 == "INFO") {info_count++}
- if ($3 == "ERROR") {error_count++}
- }
- END {
- print "order total count:"NR #NR是awk內置變量,是遍歷的當前行號,到了END區域自然行號就等於總數了
- printf("INFO count:%d ERROR count:%d\n",info_count,error_count)
- } ' demo.log_after_sort
輸出:
order total count:22
INFO count:5 ERROR count:17
例子3. 對指定時間范圍內的日志進行統計,包括輸出INFO,ERROR總數,記錄總數,每個訂單記錄分類統計
下面的例子綜合了前面sed和sort
- sed -f demo.sed demolog.log | sort -t@ -k2,2n -k3,3r -k1,1 | awk -f demo.awk
- #demo.awk
- BEGIN {
- FS="@"
- stime="2011-08-23 19:57:31"
- etime="2011-08-23 19:57:37"
- }
- $1 > stime && $1 < etime {
- if ($3 == "INFO") {info_count++}
- if ($3 == "ERROR") {error_count++}
- ++total
- status[$2]=status[$2]"\t"$1"\t"$3"\t"$4"\n"
- }
- END {
- for(i in status){
- printf("id:%s:\n%s\n",i,status[i])
- }
- print "order total count:"total
- printf("INFO count:%d ERROR count:%d\n",info_count,error_count)
- } <span style="font-size:18px;"><strong>
- </strong></span>
輸出:
id:10117:
2011-08-23 19:57:32 INFO status:attr_ids成功保存為0|100104|0|100105|100107
2011-08-23 19:57:32 ERROR status:添加屬性id,但由於認證分類參數有誤默認取匹配屬性名稱的第一個屬性id:100107
id:10226:
2011-08-23 19:57:32 INFO status:attr_ids不含0跳過
2011-08-23 19:57:32 ERROR status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100104
2011-08-23 19:57:33 ERROR status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100107
2011-08-23 19:57:33 ERROR status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:46
2011-08-23 19:57:34 ERROR status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100106
2011-08-23 19:57:35 ERROR status:添加屬性id,但由於沒有屬性在該分類下默認取匹配屬性名稱的第一個屬性id:100105
#這個例子只是舉例說明awk的統計用法,實際運用中可能會統計超時的次數,頁面訪問次數等。
awk相關資料:
《sed 與 awk》(第二版)
補充:
其他實踐時例子:
1. 在本地分支把代碼修改從一個分支復制到另一個分支(例子的b1022st.txt是一個記錄了文件新增或修改的變化的文件路徑名)
- awk 'BEGIN{FS="b1022-scm/"} {system("cp -rf b1022-scm/"$2" b1022-lpscm/"$2);}' /home/nizen/b1022st.txt
通過awk和其system命令結合,這樣就把文件從b1022-scm復制到b1022-lpscm下
2.內置函數 http://www.cnblogs.com/chengmo/archive/2010/10/08/1845913.html
3.內建變量 http://www.linuxsong.org/2010/09/awk-built-in-variable/
4.shell變量傳遞 http://www.51testing.com/?uid-225738-action-viewspace-itemid-246383
5.awk統計某個開始-結束范圍內的關鍵字累加總數:
- BEGIN {
- running=0
- count=0
- startRow="begin =====>" id #id,nextId是通過-v 參數從外部傳入
- endRow="begin =====>" nextId
- }
- $0 ~ startRow{ # ~是匹配運算符,判斷$0是否滿足startRow正則表達式
- running = 1
- # printf("start\n")
- }
- $0 ~ endRow {
- running = 0
- # printf("end\n")
- }
- {
- if(running==1) { # 僅在startRow 和 endRow 范圍內統計
- if($0 ~ "it show") {
- # printf($0 "\n")
- str=$0
- sub(/^.*show times:/, "", str)
- sub(/ .*$/, "", str)
- printf(str "\n")
- count = count + str
- }
- }
- }
- END {
- printf("showTimeCount:"+count)
- }
6. printf "10ms occur:%.2lf%%\n",t10/total*100 #輸出百分比數據,精確到百分位后2位
5.日志規范化
從前面可以看出,日志文件為了要讓后續工具能夠對里面的內容進行提取和處理,就必須要讓日志文件規范的輸出。
個人想到有幾個點可以規范:
1.記錄日志時候可以寫入一些特殊的文本語句,一遍與工具的檢索和處理。
2.記錄日志最好不要用中文,因為在不同語言環境下對日志的處理可能因為編碼不同導致沒法處理日志。
后面再貼下淘寶中找到的一些打印日志的建議:
- 正常情況下應該返回true, 卻返回false的, 反正就是你在對返回值進行檢查的時候, 如果不正常, log一下
- 出現異常的地方, 以前認為hsf.log會幫我們記下所有的異常, 但是這個也不一定可靠, 所以還得我們自己記一下
- 日志必須包含上下文信息
- 如果出於統計的需要, 可打可不打
- 在完成代碼之后, 查看一下整個代碼結構, 在一些關鍵的點, 加上日志, 正常的info, 少數情況出現的warning, 異常情況的error或者warning
- 打印的日志內容要容易查詢, 以前我比較傾向於打中文日志, 雖然易讀, 但是中文在linux下的搜索統計稍微有些麻煩,所以如果能加上英文標識(比如說用於唯一標識的前綴), 能識別不同日志, 這個對定位也是非常有好處的.
6.一些容易遇到的問題
a.處理中文出現亂碼
這個主要是因為你的linux locale的配置,與編輯文件的語言環境,還有你登錄ssh客戶端的編碼規則有關,所以最好還是不用中文記錄日志。
b.正則表達式不同工具的區別
這個主要是因為不同工具的正則表達式定義的元字符不同,網上有總結的,可點擊正則迷霧參考
OO后記:
目前只是簡單介紹了grep,sed,sort,awk的幾個簡單應用,實際上的日志監控回根據不同的情景進行不同的處理。比如需要對調用的耗時進行統計(平均時間或者超時記錄),對訪問量進行統計,但是基本原理都和本文例子出發點一致。本文一方面是為了記錄下學習過程中積累的東西,另一方面為了拋磚引玉引起大家對日志記錄的關注。
=========================================================================================================================================
http://bbs.chinaunix.net/thread-1572697-1-1.html