linux awk 命令筆記
推薦awk學習系列
https://www.ibm.com/developerworks/cn/linux/shell/awk/awk-1/index.html
https://www.ibm.com/developerworks/cn/linux/shell/awk/awk-2/index.html
https://www.ibm.com/developerworks/cn/linux/shell/awk/awk-3/index.html
工具書
https://book.saubcy.com/AwkInAction/section_1/chapter_2_1.html
1 呼叫awk方式
1.命令列方式
awk [-F field-separator] ‘commands’ input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的檔案。
在awk中,檔案的每一行中,由域分隔符分開的每一項稱為一個域。通常,在不指名-F域分隔符的情況下,預設的域分隔符是空格。2.shell指令碼方式
將所有的awk命令插入一個檔案,並使awk程式可執行,然後awk命令直譯器作為指令碼的首行,一遍通過鍵入指令碼名稱來呼叫。
相當於shell指令碼首行的:#!/bin/sh
可以換成:#!/bin/awk3.將所有的awk命令插入一個單獨檔案,然後呼叫:
awk -f awk-script-file input-file(s)
其中,-f選項載入awk-script-file中的awk指令碼,input-file(s)跟上面的是一樣的。
2 基本命令
2.1 行匹配語句 awk ” 只能用單引號
awk '{[pattern] action}' {filenames}
例
test.sh檔案
將檔案按照’\t’或者’ ‘分割,輸出第一列和第四列的內容
#!/bin/bash
awk '{print $1,$4}'
執行
chmod +x test.sh
cat b | ./test.sh
結果 輸出b檔案中每行的第一列和第四列
2.2 指定分隔符關鍵字 -F
指令碼檔案
#!/bin/bash
awk -F, '{print $1,$4}'
指定分隔符為’,’
指定多個分隔符 -F ‘[]’
指令碼檔案
#!/bin/bash
awk -F '[\t,]' '{print $1}'
先按照’\t’切分,再按照’,’切分
2.3 設定變數
用awk -v
設定變數
指令碼檔案
#/bin/bash
awk -va=1 -vb=s '{print $1,$1+a,$1b}'
$1+a
是計算第一列與變數a的和,如果$1
為字串,則只返回變數a的數值,$1b
是字串拼接,將$1
與變數a的內容連結起來
2.4 篩選匹配
指令碼檔案
#/bin/bash
awk '$1>3 && ($3 == "d" || $3 == "e") { print $0 }'
類c模式,左邊為條件,右邊為滿足條件的操作,這裡是滿足條件輸出當前行
2.5 正則
# 輸出第二列包含 "th",並列印第二列與第四列
$ awk '$2 ~ /th/ {print $2,$4}' log.txt
# 輸出包含"re" 的行
$ awk '/re/ ' log.txt
# 忽略大小寫
$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt
# 模式取反
$ awk '$2 !~ /th/ {print $2,$4}' log.txt
$cat a
1.021 33
1#.ll 44
2.53 6
ss 7
awk 'BEGIN{total = 0;len = 0} {if($1~/^[0-9]+\.[0-9]*/){total += $1; len++}} END{print total/len}' a
$1~/^[0-9]+\.[0-9]*/表示$1與“/ /”裡面的正則表示式進行匹配,若匹配,則total加上$1,且len自增,即數目加1.“^[0-9]+\.[0-9]*”是個正則表示式,“^[0-9]”表示以數字開頭,“\.”是轉義的意思,表示“.”為小數點的意思。“[0-9]*”表示0個或多個數字
3 awk指令碼
關於awk指令碼,有兩個關鍵詞BEGIN和END。
- BEGIN{ 這裡面放的是執行前的語句 }
- END {這裡面放的是處理完所有的行後要執行的語句 }
- {這裡面放的是處理每一行時要執行的語句}
檔案
$ cat 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
awk指令碼
$ cat cal.awk
#!/bin/awk -f
#執行前
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
}
執行
awk -f cal.awd score
結果
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
4 其他
awk、sed、grep更適合的方向:
- grep 更適合單純的查詢或匹配文字
- sed 更適合編輯匹配到的文字
- awk 更適合格式化文字,對文字進行較複雜格式處理
關於awk內建變數
- 解釋一下變數:
- 變數:分為內建變數和自定義變數;輸入分隔符FS和輸出分隔符OFS都屬於內建變數。
內建變數就是awk預定義好的、內建在awk內部的變數,而自定義變數就是使用者定義的變數。
FS:輸入欄位分隔符, 預設為空白字元
OFS:輸出欄位分隔符, 預設為空白字元
RS:輸入記錄分隔符(輸入換行符), 指定輸入時的換行符
ORS:輸出記錄分隔符(輸出換行符),輸出時用指定符號代替換行符
NF:當前行的欄位的個數(即當前行被分割成了幾列)
NR:行號,當前處理的文字行的行號。
FNR:各檔案分別計數的行號
ARGC:命令列引數的個數
ARGV:陣列,儲存的是命令列所給定的各引數
自定義變數的方法
方法一:-v varname=value ,變數名區分字元大小寫。
引用 http://www.runoob.com/linux/linux-comm-awk.html
5 筆記
- 執行awk指令碼傳參
awk -f test.awk a="test" filename #入參a,資料型別為string
awk -f test.awk a=1 filename #入參a,資料型別為數字
# 在指令碼呢中直接用a訪問
- awk指令碼中的陣列
#awk 遇到第一個賦值語句時,它將建立 myarray
myarray[1]="jim"
myarray[2]=456
#遍歷陣列
for ( x in myarray ) {
print myarray[x]
}
注意:每次賦值以後都迴圈一次迴圈程式碼。雖然這是一個非常方便的 awk 功能,但它有一個缺點 – 當 awk 在陣列下標之間輪轉時,它不會依照任何特定的順序。
所以輸出可能是
jim
456
也可能是
456
jim
awk的性質: 陣列下標字串化
所以awk可以當作map來使用
myarr["name"]="Mr. Whipple"
print myarr["name"]
同樣的
可以判斷key是否在array中
if ( 1 in fooarray ) {
print "Ayep! It's there."
} else {
print "Nope! Can't find it."
}
刪除元素的操作
delete fooarray[1]