本文算是學習的總結,整體是按照菜鳥教程的流程一步步練習的,多一些自己的理解
AWK:
awk [選項參數] 'script' var=value file(s)
awk [選項參數] -f scriptfile var=value file(s)
常用選項參數:
- -F fs
指定輸入文件分隔符,相當於內置變量FS
指定分割字符fs是一個字符串或者是一個正則表達式
如":"分隔-F: ","分隔-F, - -v var=value
賦值一個用戶定義變量。 - -f scripfile
從腳本文件中讀取awk命令,即指定awk腳本路徑
注意說明
- awk通過F設置(默認空格)分隔符處理每一行數據,一行中分隔符分開的每一段稱作列,用$n表示第n列,如$1
- %d表示參數是整數,%s表示參數是字符串
- 4s表示,如果不足四個字符,那麼用空格在左邊補齊。如果超過了4個,按照原樣輸出。%-5d表示顯示長度最小爲5個字符,不足的話右邊補空格,沒-是左邊補空格,有-是右邊補空格
- 關於awk腳本,我們需要注意兩個關鍵詞BEGIN和END。
BEGIN{ 這裏面放的是執行前的語句 }
END {這裏面放的是處理完所有的行後要執行的語句 }
{這裏面放的是處理每一行時要執行的語句}
test.log:
1 this is a test
learn awk
3 what do u think?
I have iphone,macbook,ipod
實例:
// 輸出test.log每一行的第一列,第四列,默認輸出分隔符(" ")
awk '{print $1,$4}' test.log
1 a
learn
3 u
I
// 格式化輸出,佔位符參考注意說明
awk '{printf "%-8s %-10s\n",$1,$4}' test.log
1 a
learn
3 u
I
// 指定","分隔符來處理每一行
awk -F, '{print $1,$2}' test.log
1 this is a test
learn awk
3 what do u think?
I have iphone macbook
// 聲明一個變量a,可以看到數字做運算,非數字當作0處理
awk -v a=1 '{print $1,$1+a}' test.log
1 2
learn 1
3 4
I 1
// 篩選第一列大於2的行,可以看到沒有{}部分對每行處理即整行輸出
awk '$1>2' test.log
learn awk
3 what do u think?
I have iphone,macbook,ipod
// 篩選第一行等於3的,輸出第一列第三列
awk '$1>=1 && $2=="what" {print $1,$2,$3}' test.log
3 what do
常用內建變量
- $n 當前記錄的第n個字段,字段間由FS分隔
- $0 完整的輸入記錄
- FNR 各文件分別計數的行號
- RS 記錄分隔符(行之間的分隔符,默認是一個換行符)
- FS 字段分隔符(列之間的分隔符,默認是任何空格)
- NF 一條記錄的字段的數目(列數)
- NR 截止當前行,已經讀出的記錄數,就是行號,從1開始
- OFS 輸出字段分隔符,即輸出時列之間分隔符
- ORS 輸出記錄分隔符(輸出換行符),即輸出時行之間分隔符
- ARGC 命令行參數的數目
- FILENAME 當前文件名
- FIELDWIDTHS 字段寬度列表(用空格鍵分隔)
- IGNORECASE 如果爲真,則進行忽略大小寫的匹配
// 注意說明提到過,BEGIN{}即讀取記錄之前的處理,在這就是格式化輸出了表頭和一行橫線
// {}是對每行數據的處理,實際值都是內建變量
awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' test.log
FILENAME ARGC FNR FS NF NR OFS ORS RS
---------------------------------------------
test.log 2 1 5 1
test.log 2 2 2 2
test.log 2 3 5 3
test.log 2 4 3 4
// 設置內建變量
awk '{print $1,$2,$5}' OFS=" $ " test.log
1 $ this $ test
learn $ awk $
3 $ what $ think?
I $ have $
// ~ 表示模式開始。針對某列的模式需要加~ ‘//’ 中是模式。
// 篩選第二列包含‘h’的行,輸出第二列第四列
awk '$2 ~ /h/ {print $2,$4}' test.log
this a
what u
have
// 設置內建變量IGNORECASE忽略大小寫,篩選包含i的行
awk 'BEGIN{IGNORECASE=1} /i/' test.log
1 this is a test
3 what do u think?
I have iphone,macbook,ipod
// !標示取反,即篩選不含i的行
awk '!/i/' test.log
learn awk
腳本
這裏要注意注意說明中的BEGIN{},{},END{}
score.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
cal.awk
#運行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#運行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#運行後
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}
// -f執行腳本文件,注意格式化輸出裏的數字爲了對其表頭,所以數字即表頭字符數和空格數
awk -f cal.awk score.txt
NAME NO. MATH ENGLISH COMPUTER TOTAL
---------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
---------------------------------------------
TOTAL: 319 393 350
AVERAGE: 63.80 78.60 70.00
// 還可以配合其他指令使用:如計算當前目錄所有txt文件大小之和
ls -l *.txt | awk '{sum+=$6} END {print sum}'
666581
// 從文件中找出長度大於80的行
awk 'length>80' log.txt