今天有個請求熔掺,想知道AIX TL升級后fileset的版本升級信息,就是從什么升到了什么非剃。
AIX方面有個方法去查看這個升級歷史瞬女,就是lslpp -h,結(jié)果加工過后如下(后來發(fā)現(xiàn)做了多余的加工)
filesetA
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetB
1.0 2/13/77
1.1 29/2/00
1.2 8/8/89
filesetC
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetD
1.0 2/13/77
1.1 29/2/00
1.2 8/8/89
filesetCA
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetCB
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetCD
1.0 2/13/77
1.1 29/2/00
1.2 8/8/89
filesetC9
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetDE
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetZP
1.0 2/13/77
1.1 29/2/00
1.2 8/8/89
filesetCW
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetCX
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetMQ
1.0 2/13/77
1.1 29/2/00
1.2 8/8/89
filesetPO
1.0 2/13/77
1.1 29/2/00
1.2 8/8/89
filesetYT
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetV
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
filesetX
1.0 2/13/77
1.1 29/2/00
1.2 8/8/88
我要找出8/8/89這個日期的段落努潘,然后版本升級前后來個可讀性增強
例如
filesetB 1.1->1.2
花了兩個小時,之前一小時花費在如何逐行判斷哪個是標題坤学,哪個是版本信息的怪圈里
然后發(fā)現(xiàn)這樣的邏輯分支太多了疯坤,簡直是自找麻煩
舉個例子,我就懶得寫了深浮,寫個大概
cat filename|while read LINE
do
if 標題的正則 $LINE压怠;then
清空臨時文件(cat /dev/null>tempfile)
titlename=“巴拉巴拉”
else
if 版本信息為空;then
versioninfo=“巴拉巴拉”
else
versioninfo="$versioninfo換行符$versioninfo"
fi
打印信息到臨時文件
unset 利用的變量(要判斷是否已有變量)
fi
done
所以就放棄了,之前弄過一個段落截取的函數(shù)飞苇,思維就開闊了菌瘫,即把標題的行數(shù)裝入數(shù)組,通過數(shù)組之間的元素弄出每個段落
[vagrant@amainst perltest]$ fileset_ck () {
> filename=$1
> keyword=$2
> list=(`grep -n ^[a-zA-Z] $filename|awk -F':' '{print $1}'`)
> i=0
> endnum=`echo ${#list[@]}`
> ubound=`expr $endnum - 1`
> while [ $i -le $ubound ]
> do
> if [ $i -eq $ubound ];then
> sed -n "${list[$i]},$"p $filename>tempfile
> else
> nextline=`expr $i + 1`
> sed -n "${list[$i]},${list[$nextline]}"p $filename|head -n -1>tempfile
> fi
> if grep -q $keyword tempfile;then
> filesetname=`head -1 tempfile`
> oldversion=`tail -2 tempfile|head -n -1|awk '{print $1}'`
> newversion=`tail -1 tempfile|awk '{print $1}'`
> echo -e "$filesetname\t$oldversion->$newversion"
> fi
> i=`expr $i + 1`
> done
> unset filename keyword listi filesetname oldversion newversion
> }
[vagrant@amainst perltest]$ time fileset_ck testfile 89
filesetB 1.1->1.2
filesetD 1.1->1.2
filesetCD 1.1->1.2
filesetZP 1.1->1.2
filesetMQ 1.1->1.2
filesetPO 1.1->1.2
real 0m0.117s
user 0m0.059s
sys 0m0.056s
看到這里請注意2伎āS耆谩!7薜取F苤摇!以上都是在浪費時間贸街,再經(jīng)過冷靜思考以后我想起aix的grep是有關(guān)鍵字段落的參數(shù)的庵寞,那就grep -p 關(guān)鍵字
但是我現(xiàn)在用的是centos來寫記錄這些體驗,centos(一切l(wèi)inux發(fā)行版)怎么弄段落呢薛匪?
那就是awk中對于RS這個保留字的理解捐川,RS是記錄的分隔符。
以下是命令
以下命令有點長
首先管道sed把首字符為英文的行前插入兩個空行逸尖,這樣好處理段落(其實數(shù)據(jù)本來就是段落古沥,我還特意把空行刪掉了)
然后awk BEGIN語句里對awk進行一個記錄分隔符的設(shè)定(RS="\n\n")就是兩個空行前的數(shù)據(jù)為一個記錄
[vagrant@amainst perltest]$ time cat testfile|sed '/^[a-zA-Z]/i\\n'|awk 'BEGIN{RS="\n\n"}
> /89/{sub("\n","",$0)#這里匹配關(guān)鍵字89,因為我要找的數(shù)據(jù)是這個冷溶,其實不夠嚴謹渐白,但目前數(shù)據(jù)源沒有多余的數(shù)據(jù)干擾。
> ubound=split($0,info,"\n")#變量=split這種方法之前的文章有提到逞频,就是找出split出來的數(shù)組的長度纯衍。
> print info[1]"\t"info[ubound-1]" -> "info[ubound]}'|awk 'BEGIN{OFS="\t"}{NF=NF;$NF=$(NF-3)="";print}'
#最后一個管道是因為懶得在前一個awk管道處理了,就放到這里來
filesetB 1.1 -> 1.2
filesetD 1.1 -> 1.2
filesetCD 1.1 -> 1.2
filesetZP 1.1 -> 1.2
filesetMQ 1.1 -> 1.2
filesetPO 1.1 -> 1.2
real 0m0.005s#主要看這里的視角消耗苗胀,比前一個shell快多了
user 0m0.004s
sys 0m0.001s
為什么awk的方法要比shell快
對于性能的問題襟诸,最好都去研究一下時間復(fù)雜度的問題瓦堵。(老實說我自己也解釋不清楚)
以下是初淺理解
[vagrant@amainst perltest]$ echo ${#list[@]}
17
shell數(shù)組的長度是17,時間復(fù)雜度來看歌亲,里面只有一個循環(huán)菇用,應(yīng)該是O(n),即O(17)
[vagrant@amainst perltest]$ cat testfile|sed '/^[a-zA-Z]/i\\n'|awk 'BEGIN{RS=OFS="\n\n"}{print NR}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
awk的記錄比shell還多一個陷揪,哈哈惋鸥,即O(18)
[vagrant@amainst perltest]$ cat testfile|sed '/^[a-zA-Z]/i\\n'|awk 'BEGIN{RS=OFS="\n\n"}/89/{print NR}'
3
5
8
11
14
15
但是匹配關(guān)鍵字后記錄只有6,即O(6)悍缠,那是不是快在這里呢卦绣?
花了一天時間,不得不說shell寫法不僅耗時久(寫的也久飞蚓,語法的符號用多了還容易出語法錯誤)滤港。
推薦如果會awk,多花時間學(xué)習趴拧,書寫效率和執(zhí)行效率都要比shell快溅漾。
最后,用shell也千萬不要用逐行循環(huán)
[vagrant@amainst perltest]$ wc -l testfile
68 testfile
以上著榴,程序要處理68行數(shù)據(jù)添履,即O(68),執(zhí)行效率可想而知脑又。