序
因為經常做awk編碼,而且跨過一段時間就容易忘記,故在此做個留底。便于翻閱。——后期會在這個頁面不斷補充!
常用常量
| 屬性 | 描述 |
|---|---|
| NR | 已讀入的總記錄數 |
| ARGIND | 當前被處理參數標志 |
| FILENAME | 當前輸入文件名 |
| FS | 輸入域分隔符,默認為一個空格 |
| RS | 輸入記錄分隔符 |
| NF | 當前記錄里域個數 |
| SUBSEP | 下標分隔符 "\034" |
獲取日期
strftime("%Y-%m-%d", systime())
加載awk文件方式
awk -v "file_name=`basename $file`" -f cut_online.awk $file
處理多個文件的時候,區分文件

區分:

awk的數組,一種關聯數組(Associative Arrays),下標可以是數字和字符串。因無需對數組名和元素提前聲明,也無需指定元素個數 ,所以awk的數組使用非常靈活。
首先介紹下幾個awk數組相關的知識點:
<1>建立數組
array[index] = value :數組名array,下標index以及相應的值value。
<2>讀取數組值
{ for (item in array) print array[item]} # 輸出的順序是隨機的
{for(i=1;i<=len;i++) print array[i]} # Len 是數組的長度
<3>多維數組,array[index1,index2,……]:SUBSEP是數組下標分割符,默認為“\034”。可以事先設定SUBSEP,也可以直接在SUBSEP的位置輸入你要用的分隔符,如:
awk 'BEGIN{SUBSEP=":";array["a","b"]=1;for(i in array) print i}' a:b awk 'BEGIN{array["a"":""b"]=1;for(i in array) print i}' a:b
但,有些特殊情況需要避免,如:
awk 'BEGIN{ SUBSEP=":" array["a","b:c"]=1 # 下標為“a:b:c” array["a:b","c"]=2 #下標同樣是“a:b:c” for (i in array) print i,array[i]}' a:b:c 2 #所以數組元素只有一個。
<4>刪除數組或數組元素: 使用delete 函數
delete array #刪除整個數組
delete array[item] # 刪除某個數組元素(item)
<5> 排序:awk中的asort函數可以實現對數組的值進行排序,不過排序之后的數組下標改為從1到數組的長度。在gawk 3.1.2以后的版本還提供了一個asorti函數,這個函數不是依據關聯數組的值,而是依據關聯數組的下標排序,即asorti(array)以后,仍會用數字(1到數組長度)來作為下標,但是array的數組值變為排序后的原來的下標,除非你指定另一個參數如:asorti(a,b)。
echo 'aa bb aa bb cc' |\ awk '{a[$0]++}END{l=asorti(a);for(i=1;i<=l;i++)print a[i]}' aa bb cc echo 'aa bb aa bb cc' |\ awk '{a[$0]++}END{l=asorti(a,b);for(i=1;i<=l;i++)print b[i],a[b[i]]}' aa 2 bb 2 cc 1
| 屬性 | 描述 |
|---|---|
| asort | asort對數組進行排序,返回數組長度 |
練習1(分析出每天有多少員工離職?有多少員工入職?)
awk代碼(test_log_info.awk)
BEGIN{ today = strftime("%Y-%m-%d-%H", systime()); } FILENAME == ARGV[1]{ # 第一個文件 舊記錄 old_user[$1] = $0; } FILENAME == ARGV[2]{ # 第二個文件 新紀錄 new_user[$1] = $0; } END{ log_info = ""; log_file = log_dir"user_log_info.log."today""; for(old_uid in old_user){ if(new_user[old_uid] == ""){ log_info = log_info"leave user:"old_user[old_uid]"\n"; delete new_user[new_uid]; } } for(new_uid in new_user){ if(old_user[new_uid] == ""){ log_info = log_info"add user:"new_user[new_uid]"\n"; delete old_user[new_uid]; } } log_info = log_info"old count:"asort(old_user)";new count:"asort(new_user); system(" echo '"log_info"' > "log_file); }
分析日志shell腳本(test_log_info.sh)
#!/bin/bash yesterday(){ yy=`date +%Y` #Year yyyy mm=`date +%m` #Month mm dd=`date +%d` #Day dd if [ $dd = "01" ] then lm=`expr $mm - 1 ` if [ $lm -eq 0 ] then lm=12 yy=`expr $yy - 1 ` fi echo lm=$lm case $lm in 1|3|5|7|8|10|12) Yesterday=31 ;; 4|6|9|11) Yesterday=30 ;; 2) if [ ` expr $yy % 4 ` -eq 0 -a `expr $yy % 100 ` -ne 0 -o ` expr $yy % 400 ` -eq 0 ] then Yesterday=29 else Yesterday=28 fi ;; esac mm=$lm Yesterday=$Yesterday else Yesterday=`expr $dd - 1 ` fi case $Yesterday in 1|2|3|4|5|6|7|8|9) Yesterday='0'$Yesterday esac case $mm in 1|2|3|4|5|6|7|8|9) mm='0'$mm ;; esac Yesterday=$yy"-"$mm"-"$Yesterday"-05" } yesterday Today=`date "+%Y-%m-%d-05"` TEMP_DIR="/home/rd/zhoubc/bak/" awk -v "log_dir="$TEMP_DIR -f test_log_info.awk $BAKDIR""test2.conf.""$Yesterday $BAKDIR""test2.conf.""$Today
調用嵌套的shell文件(test_send.sh)
#!/bin/bash BAKDIR='/home/crontab/send_user/bak/' source test_log_info.sh
調用:

幾個技術點:
shell腳本套用(source)——這樣可以公用變量
source test_log_info.sh
awk多文件分別處理:
FILENAME == ARGV[1]{}
FILENAME == ARGV[2]{}
案例1:統計每個分類下,樣本的中位數
數據結構:
下標從1開始計算。第二列為分類ID,第11類為月日均pv量。
325 20 230 4918 4 1 64 0 0 64.72 36.9 25 26 803 25 33 249 4 0 74 0 0 4.0 3.5 3 2 841 0 566 8624 11 21 269 1 0 527.57 415.6 1331 825 858 8 498 11569 21 17 477 1 0 1386.29 913.87 2787 2982 1004 6 221 3222 15 7 176 1 0 900.28 673.36 712 458
相關代碼:
# $11 是月日均pv量
function ceil(x){
y = int(x);
return (x > y ? y + 1 : y)
}
# 取中位數
function get_median(arr){
len = asort(arr);
#for(i = 1; i <= len; i++) {
# printf("%d\t", arr[i]);
#}
#printf("\n");
mid = ceil(len/ 2);
if(len%2 == 0){
return ceil((arr[mid] + arr[mid + 1]) / 2);
}
#printf("mid=%d\n", mid);
return arr[mid];
}
BEGIN{
}
{
if(!($2 in cardTypeTree)){
cardTypeTree[$2] = $11;
} else {
cardTypeTree[$2] = cardTypeTree[$2]"_"$11;
}
}
END{
system("rm -f ./parseType.txt")
for(key in cardTypeTree){
split(cardTypeTree[key], array, "_")
printf("%-10s\t%d\t%-10s\n", key, length(array), get_median(array))
system("echo '"key"\t"length(array)"\t"get_median(array)"' >> ./parseType.txt")
}
}
執行結果如下:
總結
工作中斷斷續續會用到awk腳本,老是用去搜索太麻煩了,故放在這里,方便日后查閱。如果對你有幫助,就推薦一下!
推薦

喜歡編程
浙公網安備 33010602011771號