[Shell] awk初學之常見問題
awk初學之常見問題
(轉載)
1. awk ‘{code}1’ 中的“1”是幹什麼的?
一個完整的awk語句為:Awk ‘[patten]{action}……’, 其中pattern預設為1,action預設為{print}.
那麼awk ‘1’完整的寫法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的寫法也是awk ‘1{print}’.
2. NR和FNR的區別是啥?
NR: 當前行記錄數。
FNR: 當前檔案的行記錄數。
當awk處理的檔案數超過1時,NR和FNR才會有區別。例如:
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
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
推薦使用第一種方法,這樣可以避免一些不必要的煩惱。如
4. 為什麼OFS不起作用?
先看一個例子:
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
上面的例子中OFS為什麼沒有生效呢,原因是OFS指的是輸出欄位分隔符,所以必須對欄位進行操作時OFS才會起作用,正確的方法應該是:
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
正如Tim大師所講的,$1=$1這個action,是我們對awk撒的謊,目的就是為了使得OFS生效,除此之外,NF+=0也是常用的方法。
5. 同樣的程式碼,別人執行成功,為什麼我執行失敗?
這個問題的原因很多,我這裡列舉兩個最常見的,大家可以補充。
1: awk版本引起的,如gawk中的一些擴充套件函式或變數,在nawk中沒有,或是不同版本的(g/n)awk也會有差別,這樣情況需要重新編寫。
2: 文字格式的問題,cat-A file檢視一下,如果是,dos2unix應該可以解決。
注:書寫錯誤也有可能哦
6. Awk 語句中可以使用{n,m}這樣的正則麼?
可以,使用方法:gawk -- re-interval ,其它版本使用方法會有所不同,請大家補充
7. BEGIN 和END 到底是怎麼一回事?
有時,對於新手可能也會是個問題。簡單說下:
BEGIN {action} : 讀取文字之前進行的操作。要避免類似下面的寫法:
awk 'BEGIN{ filename = FILENAME}' file
# or:
awk 'BEGIN{FS=":"; for(i=2;i<=NF;i++) print $i}' file
如果BEGIN 模組中使用getline函式時,情況會有所不同:
cat file
1
2
3
4
5
awk 'BEGIN{while (getline <"file") print}' file
1
2
3
4
5
END {action}:
它在整個輸入檔案處理完成後被執行,同樣無法對文字進行任何操作,如匹配某個pattern執行action。
8. print,printf 和sprintf?
print:為一般的列印
printf:可以定義列印格式
sprintf:可以完成和printf相同的功能,不同的是sprintf只能輸出值,並不能完成列印的功能。
print預設有個換行\n,
而printf沒有,當然它和C語言的printf類似(awk本是c的近親),能列印各種格式,但預設沒有換行。
例如:
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
9. “a==b?c:d” ?
這個是一個if語句的簡寫,即conditional expression1 ? expression2: expression3;完整寫法為:
if(a==b) {c} else {d}
10. awk ‘! a[$0]++’ 怎麼理解?
這是一個非常經典的去重複項的awk語句,雖然短小,不過涉及到了不少知識點,下面一一解讀:
1 :”!” 即非。
2:a[$0],以$0為資料下標,建立陣列a
3:a[$0]++,即給陣列a賦值,a[$0]+=1
4 :那麼組合起來,awk是怎麼執行!a[$0]++的呢?我用一個實際例子來解釋:
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
原來,第一個a[$0]的值為空,所以!a[$0]++是先作判斷,結果為1(非空為真,即為1),再作陣列賦值a[$0]++。這也就是為什麼前面的!a[$0]++並不一定等於後面的!a[$0]。
awk ‘++a[$0]==1’ 和上面的程式碼作用一樣,你理解了麼?
11. 如何列印單雙引號?
awk 'BEGIN {print "single quote --> '\''";print "double quote --> \"" }'
single quote --> '
double quote --> "
更可靠的的方法如Tim所示:
awk 'BEGIN {print "single quote --> \047";print "double quote --> \042" }'
12. awk 語句中多個{}是怎麼執行的?
還是用個例子來說明:
cat file
1
2
3
4
5
awk '$1==3{printf "|| "$0}{printf " @@ "$0}{print $0}' file # 這個語句中包含三個action
@@ 11 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
@@ 22 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
|| 3 @@ 33 # 判斷$1==3?是,執行{print “|| “$0}; 執行 action {printf " @@ "$0};執行 action {print $0}
@@ 44 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
@@ 55 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
這樣可以清楚的看出,awk是一行一行讀取文字,然後按照程式碼的前後順序執行。但如果action中包含next或exit時,有所不同:
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
(轉載)
1. awk ‘{code}1’ 中的“1”是幹什麼的?
一個完整的awk語句為:Awk ‘[patten]{action}……’, 其中pattern預設為1,action預設為{print}.
那麼awk ‘1’完整的寫法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的寫法也是awk ‘1{print}’.
2. NR和FNR的區別是啥?
NR: 當前行記錄數。
FNR: 當前檔案的行記錄數。
當awk處理的檔案數超過1時,NR和FNR才會有區別。例如:
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
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
推薦使用第一種方法,這樣可以避免一些不必要的煩惱。如
4. 為什麼OFS不起作用?
先看一個例子:
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
上面的例子中OFS為什麼沒有生效呢,原因是OFS指的是輸出欄位分隔符,所以必須對欄位進行操作時OFS才會起作用,正確的方法應該是:
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
正如Tim大師所講的,$1=$1這個action,是我們對awk撒的謊,目的就是為了使得OFS生效,除此之外,NF+=0也是常用的方法。
5. 同樣的程式碼,別人執行成功,為什麼我執行失敗?
這個問題的原因很多,我這裡列舉兩個最常見的,大家可以補充。
1: awk版本引起的,如gawk中的一些擴充套件函式或變數,在nawk中沒有,或是不同版本的(g/n)awk也會有差別,這樣情況需要重新編寫。
2: 文字格式的問題,cat-A file檢視一下,如果是,dos2unix應該可以解決。
注:書寫錯誤也有可能哦
6. Awk 語句中可以使用{n,m}這樣的正則麼?
可以,使用方法:gawk -- re-interval ,其它版本使用方法會有所不同,請大家補充
7. BEGIN 和END 到底是怎麼一回事?
有時,對於新手可能也會是個問題。簡單說下:
BEGIN {action} : 讀取文字之前進行的操作。要避免類似下面的寫法:
awk 'BEGIN{ filename = FILENAME}' file
# or:
awk 'BEGIN{FS=":"; for(i=2;i<=NF;i++) print $i}' file
如果BEGIN 模組中使用getline函式時,情況會有所不同:
cat file
1
2
3
4
5
awk 'BEGIN{while (getline <"file") print}' file
1
2
3
4
5
END {action}:
它在整個輸入檔案處理完成後被執行,同樣無法對文字進行任何操作,如匹配某個pattern執行action。
8. print,printf 和sprintf?
print:為一般的列印
printf:可以定義列印格式
sprintf:可以完成和printf相同的功能,不同的是sprintf只能輸出值,並不能完成列印的功能。
print預設有個換行\n,
而printf沒有,當然它和C語言的printf類似(awk本是c的近親),能列印各種格式,但預設沒有換行。
例如:
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
9. “a==b?c:d” ?
這個是一個if語句的簡寫,即conditional expression1 ? expression2: expression3;完整寫法為:
if(a==b) {c} else {d}
10. awk ‘! a[$0]++’ 怎麼理解?
這是一個非常經典的去重複項的awk語句,雖然短小,不過涉及到了不少知識點,下面一一解讀:
1 :”!” 即非。
2:a[$0],以$0為資料下標,建立陣列a
3:a[$0]++,即給陣列a賦值,a[$0]+=1
4 :那麼組合起來,awk是怎麼執行!a[$0]++的呢?我用一個實際例子來解釋:
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
原來,第一個a[$0]的值為空,所以!a[$0]++是先作判斷,結果為1(非空為真,即為1),再作陣列賦值a[$0]++。這也就是為什麼前面的!a[$0]++並不一定等於後面的!a[$0]。
awk ‘++a[$0]==1’ 和上面的程式碼作用一樣,你理解了麼?
11. 如何列印單雙引號?
awk 'BEGIN {print "single quote --> '\''";print "double quote --> \"" }'
single quote --> '
double quote --> "
更可靠的的方法如Tim所示:
awk 'BEGIN {print "single quote --> \047";print "double quote --> \042" }'
12. awk 語句中多個{}是怎麼執行的?
還是用個例子來說明:
cat file
1
2
3
4
5
awk '$1==3{printf "|| "$0}{printf " @@ "$0}{print $0}' file # 這個語句中包含三個action
@@ 11 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
@@ 22 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
|| 3 @@ 33 # 判斷$1==3?是,執行{print “|| “$0}; 執行 action {printf " @@ "$0};執行 action {print $0}
@@ 44 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
@@ 55 # 判斷$1==3?否;執行 action {printf " @@ "$0};執行 action {print $0}
這樣可以清楚的看出,awk是一行一行讀取文字,然後按照程式碼的前後順序執行。但如果action中包含next或exit時,有所不同:
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
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24237320/viewspace-2103812/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 初學python的常見問題Python
- React + Typescript領域初學者的常見問題和技巧ReactTypeScript
- NSIS 之 NsDialogs 常見問題解答
- Python學習常見問題分享!Python
- 常見問題
- 學習WebFlux時常見的問題WebUX
- 雲端計算面試常見問題,怎麼理解shell?面試
- ES系列二之常見問題解決
- PostgreSQL/LightDB分割槽表之常見問題SQL
- XSS常見問題
- Mysql:常見問題MySql
- MyBatis常見問題MyBatis
- 【Nginx】常見問題Nginx
- ndk 常見問題
- java 常見問題Java
- js常見問題JS
- Homestead 常見問題
- Apache 常見問題Apache
- Linux 常見問題Linux
- Git 常見問題Git
- PHP 常見問題PHP
- swiper常見問題
- Composer 常見問題
- CSS常見問題CSS
- nginx 常見問題Nginx
- HTML常見問題HTML
- Git常見問題Git
- 前端常見問題前端
- awk小技巧之執行shell命令
- 前端面試之webpack面試常見問題前端面試Web
- phpMyAdmin工具常見問題PHP
- c++ 常見問題C++
- APatch常見問題解答
- 字串混淆常見問題字串
- RapidWeaver 8常見問題API
- Android Studio常見問題(+)Android
- weex常見問題解析
- sonar常見問題分析
- CSS效果常見問題CSS