本帖最后由 yinyuemi 于 2016-12-08 16:14 編輯
從初學(xué)awk到現(xiàn)在小有所成,非常感謝CUers的幫助,總結(jié)了下自己曾經(jīng)遇到的問(wèn)題和犯的錯(cuò)誤,供初學(xué)者借鑒,因本人非計(jì)算機(jī)專(zhuān)業(yè),對(duì)專(zhuān)業(yè)詞匯可能有表述不對(duì)的地方,還請(qǐng)指正和補(bǔ)充!
1. awk ‘{code}1’ 中的“1”是干什么的? 一個(gè)完整的awk語(yǔ)句為:Awk ‘[patten]{action}……’, 其中pattern缺省為1,action缺省為{print}。 那么awk ‘1’完整的寫(xiě)法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的寫(xiě)法也是awk ‘1{print}’。
2. NR和FNR的區(qū)別是啥? NR: 當(dāng)前行記錄數(shù)。 FNR: 當(dāng)前文件的行記錄數(shù)。 當(dāng)awk處理的文件數(shù)超過(guò)1時(shí),NR和FNR才會(huì)有區(qū)別。例如:
- cat file
- a
- b
- c
- d
- e
- f
- awk '{print "NR = " NR " FNR = " FNR, $0}' file
- NR = 1 FNR = 1 a
- NR = 2 FNR = 2 b
- NR = 3 FNR = 3 c
- NR = 4 FNR = 4 d
- NR = 5 FNR = 5 e
- NR = 6 FNR = 6 f
- awk '{print "NR = " NR " FNR = " FNR, $0}' file file
- NR = 1 FNR = 1 a
- NR = 2 FNR = 2 b
- NR = 3 FNR = 3 c
- NR = 4 FNR = 4 d
- NR = 5 FNR = 5 e
- NR = 6 FNR = 6 f
- NR = 7 FNR = 1 a
- NR = 8 FNR = 2 b
- NR = 9 FNR = 3 c
- NR = 10 FNR = 4 d
- NR = 11 FNR = 5 e
- NR = 12 FNR = 6 f
復(fù)制代碼
3. Awk怎么引入變量? 有兩種方法: <1>: awk -v var=$VAR '{code}'
<2>: awk '{CODE}'$VAR'{CODE}'
例如:
- VAR=XXX
- awk -v var=$VAR 'BEGIN{print var}'
- XXX
- awk 'BEGIN{print "'$VAR'"}'
- XXX
復(fù)制代碼
我推薦使用第一種方法,這樣可以避免一些不必要的煩惱。如http://72891.cn/thread-1835620-1-1.html
4. 為什么OFS不起作用? 先看一個(gè)例子:
- echo 'aaa bbb ccc ddd
- aaa bbb ccc ddd
- aaa bbb ccc ddd
- aaa bbb ccc ddd' |awk -v OFS="|" '{print $0}'
- aaa bbb ccc ddd
- aaa bbb ccc ddd
- aaa bbb ccc ddd
- aaa bbb ccc ddd
復(fù)制代碼
上面的例子中OFS為什么沒(méi)有生效呢,原因是OFS指的是輸出字段分隔符,所以必須對(duì)字段進(jìn)行操作時(shí)OFS才會(huì)起作用,正確的方法應(yīng)該是:
- echo 'aaa bbb ccc ddd
- aaa bbb ccc ddd
- aaa bbb ccc ddd
- aaa bbb ccc ddd' |awk -v OFS="|" '{$1=$1;print $0}'
- aaa|bbb|ccc|ddd
- aaa|bbb|ccc|ddd
- aaa|bbb|ccc|ddd
- aaa|bbb|ccc|ddd
復(fù)制代碼
正如Tim大師所講的,$1=$1這個(gè)action,是我們對(duì)awk撒的謊,目的就是為了使得OFS生效,除此之外,NF+=0也是常用的方法。參考:http://72891.cn/viewthread.php?tid=1354674&extra=&page=1
5. 同樣的代碼,別人運(yùn)行成功,為什么我運(yùn)行失。 這個(gè)問(wèn)題的原因很多,我這里列舉兩個(gè)最常見(jiàn)的,大家可以補(bǔ)充。 <1>: awk版本引起的,如gawk中的一些擴(kuò)展函數(shù)或變量,在nawk中沒(méi)有,或是不同版本的(g/n)awk也會(huì)有差別,這樣情況需要重新編寫(xiě)。 <2>: 文本格式的問(wèn)題,cat-A file查看一下,如果是,dos2unix應(yīng)該可以解決。 注:書(shū)寫(xiě)錯(cuò)誤也有可能哦
6. Awk 語(yǔ)句中可以使用{n,m}這樣的正則么? 可以,使用方法:gawk -- re-interval ,其它版本使用方法會(huì)有所不同,請(qǐng)大家補(bǔ)充
7. BEGIN 和END 到底是怎么一回事? 有時(shí),對(duì)于新手可能也會(huì)是個(gè)問(wèn)題。簡(jiǎn)單說(shuō)下: BEGIN {action} : 讀取文本之前進(jìn)行的操作。要避免類(lèi)似下面的寫(xiě)法:
- awk 'BEGIN{ filename = FILENAME}' file
- # or:
- awk 'BEGIN{FS=":"; for(i=2;i<=NF;i++) print $i}' file
復(fù)制代碼
如果BEGIN 模塊中使用getline函數(shù)時(shí),情況會(huì)有所不同:
- cat file
- 1
- 2
- 3
- 4
- 5
- awk 'BEGIN{while (getline <"file") print}' file
- 1
- 2
- 3
- 4
- 5
復(fù)制代碼END {action}:
它在整個(gè)輸入文件處理完成后被執(zhí)行,同樣無(wú)法對(duì)文本進(jìn)行任何操作,如匹配某個(gè)pattern執(zhí)行action。
8. print,printf 和sprintf? print:為一般的打印 printf:可以定義打印格式 sprintf:可以完成和printf相同的功能,不同的是sprintf只能輸出值,并不能完成打印的功能。
12樓-expert1補(bǔ)充::) print默認(rèn)有個(gè)換行\(zhòng)n,
而printf沒(méi)有,當(dāng)然它和C語(yǔ)言的printf類(lèi)似(awk本是c的近親),能打印各種格式,但默認(rèn)沒(méi)有換行。
例如:
- awk 'BEGIN{var=123; print "var = " var}'
- var = 123
- awk 'BEGIN{var=123;printf "%s %5f\n", "var =",var}'
- var = 123.000000
- awk 'BEGIN{var=123;sprintf ("%s %5f\n", "var =",var)}'
- awk ‘BEGIN{var1=123;var2=sprintf ("%5f",var1); print "var2 =" var2}’
- var2 = 123.000000
復(fù)制代碼
9. “a==b?c:d” ? 這個(gè)是一個(gè)if語(yǔ)句的簡(jiǎn)寫(xiě),即conditional expression1 ? expression2: expression3;完整寫(xiě)法為: if(a==b) {c} else a9ur7n9vt
10. awk ‘! a[$0]++’ 怎么理解? 這是一個(gè)非常經(jīng)典的去重復(fù)項(xiàng)的awk語(yǔ)句,雖然短小,不過(guò)涉及到了不少知識(shí)點(diǎn),下面一一解讀: <1> :”!” 即非。 <2>:a[$0],以$0為數(shù)據(jù)下標(biāo),建立數(shù)組a <3>:a[$0]++,即給數(shù)組a賦值,a[$0]+=1 <4> :那么組合起來(lái),awk是怎么執(zhí)行!a[$0]++的呢?我用一個(gè)實(shí)際例子來(lái)解釋?zhuān)?/p>
- cat file
- 111
- 222
- 111
- 222
- 333
- awk '{print a[$0],!a[$0]++,a[$0],!a[$0],$0}' file
- 1 1 0 111
- 1 1 0 222
- 1 0 2 0 111
- 1 0 2 0 222
- 1 1 0 333
復(fù)制代碼
https://www.gnu.org/software/gaw ... .html#Increment-Ops
lvalue++Increment lvalue, returning the old value of lvalue as the value of the expression. awk ‘++a[$0]==1’ 和上面的代碼作用一樣,你理解了么?
11. 如何打印單雙引號(hào)?
- awk 'BEGIN {print "single quote --> '\''";print "double quote --> \"" }'
- single quote --> '
- double quote --> "
復(fù)制代碼
更可靠的的方法如Tim所示:
- awk 'BEGIN {print "single quote --> \047";print "double quote --> \042" }'
復(fù)制代碼12. awk 語(yǔ)句中多個(gè){}是怎么執(zhí)行的? 還是用個(gè)例子來(lái)說(shuō)明:
- cat file
- 1
- 2
- 3
- 4
- 5
- awk '$1==3{printf "|| "$0}{printf " @@ "$0}{print $0}' file # 這個(gè)語(yǔ)句中包含三個(gè)action
- @@ 11 # 判斷$1==3?否;執(zhí)行 action {printf " @@ "$0};執(zhí)行 action {print $0}
- @@ 22 # 判斷$1==3?否;執(zhí)行 action {printf " @@ "$0};執(zhí)行 action {print $0}
- || 3 @@ 33 # 判斷$1==3?是,執(zhí)行{print “|| “$0}; 執(zhí)行 action {printf " @@ "$0};執(zhí)行 action {print $0}
- @@ 44 # 判斷$1==3?否;執(zhí)行 action {printf " @@ "$0};執(zhí)行 action {print $0}
- @@ 55 # 判斷$1==3?否;執(zhí)行 action {printf " @@ "$0};執(zhí)行 action {print $0}
復(fù)制代碼
這樣可以清楚的看出,awk是一行一行讀取文本,然后按照代碼的前后順序執(zhí)行。但如果action中包含next或exit時(shí),有所不同:
- awk '$1==3{printf "|| "$0;next}{printf "@@ "$0}{print $0}' file
- @@ 11
- @@ 22
- || 3@@ 44
- @@ 55
- awk '$1==3{printf "|| "$0;exit}{printf "@@ "$0}{print $0}' file
- @@ 11
- @@ 22
- || 3
復(fù)制代碼
13. FS, OFS, RS, ORS? 最后用圖解的方式說(shuō)明一下這四個(gè)變量: |