1. 程式人生 > >shell指令碼不排序去重

shell指令碼不排序去重

一條命令搞定:

awk '!a[$0]++' file

如果是第一次出現a[$0]++的值為0(假),而!a[$0]++的值就為1(真),之後就執行print $0

第二次或者兩次以上的出現a[$0]++的值就為大於0的整數值(真),例如1,2,3...,而!a[$0]++的值就為0(假),之後就不執行print $0操作

awk '!($0 in a){a[$0];print $0}'

pattern為!($0 in a),Action為{a[$0];print $0}

分析:

1.執行第一行時的a的陣列為空,($0 in a)為假,!($0 in a)為真。執行Action,a[$0]就存在了a[row1],列印第一行

2.執行第二行時的a的陣列為a[row1],如果a[row2] 是a[$0]中的元素,!($0 in a)為真為假,不執行Ation。如果a[row2]不是a[$0]中的元素,執行Action,a[$0]中增加元素(a[row1],a[row2]),列印第二行。

3.重複執行類似的第二步驟。達到的去重的效果。

此種去重結果為整個文字沒有重複項。

解釋下
awk '!a[$0]++' file

一看之下,首先是想到又用到awk的hash,又是預設的pattern,一下子來了興趣,做了以下的分析

這個要從awk的執行模式開始說,最後結合++運算子,和hash特色
有三個基本知識點是要了解的
1:a++的作用是先附值,再累加a,與++a正好相反。

2:hash的初始是undef,通過直接賦值或宣告進行定義,如a[1]=1,或直接宣告a[1]。

3:awk的基本模式是,pattern   { action statements },action部分是可以省略的,預設情況下是輸出,即{print $0},至於pattern可以理解成是表示式,通過pattern表示式的值的真假,來確定是否要進行action。比如1,最簡單的awk用來實現cat的功能就是 awk '1',這邊1就是pattern,當然,1也可以是2,3,4,5等其他數字,但如果用字母的話,就不行,因為字母會解釋成變數,變數初始值未定義,初始值為假,或者可以加個!反義

結合上邊三點來分析awk '!a[$0]++' file
"!a[$0]++"

0:整個模式,沒有用到action,所以採用的是預設的{print $0},即在patten為真條件來,輸出行
patten分析:
1:使用了一個hash陣列,a,陣列的鍵值採用$0,即每行值
2:當a[$0]未宣告時,a[$0]為假,在未宣告的情況下,進行一次a[$0]++後,a[$0]即為真
3:!取反
結論:當相同的行第一次讀入時,pattern為真,行輸出,再次讀入後,patten為假,行乎略

基本理論知道了,要用得出來還得多鍛鍊應用

上週幫別人寫個awk,也是這種情況
我寫的
awk '{if($2 in a);else{a[$2]=$0}}END{for(b in a)print a[b]}' urrfile

後來別人給出更簡單的答案
awk ' !($2 in i){ i[$2]; print } ' urrfile

現在看來,還可以更簡單些
awk '!a[$2]++' urrfile

     #To get missed_strings.txt which /values-xxx exist but /values does
not exist
     ./vendor/jrdcom/build/jrdtools/stringtool/prebuilt/stringtool.sh -v
-i ./vendor/jrdcom/build/common/string_res.ini -p ./ >> ./OriMissStrings.txt
     grep -v "Language" ./OriMissStrings.txt >> ./temp_del_lan.txt
     cat temp_del_lan.txt | tr -d "[" | tr -d "]" | tr -d "{" | tr -d
"}" >> ./temp_del_char.txt
     awk '!a[$0]++' ./temp_del_char.txt >> ./missed_strings.txt
     rm ./temp_del_lan.txt ./temp_del_char.txt