awk是linux/unix一種適用于文本文件處理的工具。
gawk是awk的GNU版本,它提供了Bell實驗室和GNU的一些擴展。
使用命令格式與參數
Usage: awk [POSIX or GNU style options] -f progfile [--] file ... #從腳本文件中讀取awk命令
Usage: awk [POSIX or GNU style options] [--] 'program' file ...#program可以是位于大括號內由換行符或分號隔開的多個命令
POSIX options: GNU long options: (standard)
-f progfile --file=progfile #從腳本讀取awk程序
-F fs --field-separator=fs #文件每行分隔符
-v var=val --assign=var=val #使用者自定義變量;-v a=1:自定義變量a
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version
基本概念:
記錄: awk把每一個以換行符結束的行稱為一個記錄。
記錄分隔符:默認的輸入和輸出的分隔符都是回車,保存在內建變量ORS和RS中。
$0變量:它指的是整條記錄。如$ awk '{print $0}' test將輸出test文件中的所有記錄。
變量NR:一個計數器,每處理完一條記錄,NR的值就增加1。如$ awk '{print NR,$0}' test將輸出test文件中所有記錄,并在記錄前顯示記錄號。
域: 記錄中每個單詞稱做“域”,默認情況下以空格或tab分隔。awk可跟蹤域的個數,并在內建變量NF中保存該值。如$ awk '{print $1,$3}' test將打印test文件中第一和第三個以空格分開的列(域)。
域分隔符: 內建變量FS保存輸入域分隔符的值,默認是空格或tab。我們可以通過-F命令行選項修改FS的值。
$awk -F: '{print $1,$5}' test # 將打印以冒號為分隔符的第一,第五列的內容。可以同時使用多個域分隔符,這時應該把分隔符寫成放到方括號中;
$awk -F'[:\t]' '{print $1,$3}' test # 表示以空格、冒號和tab作為分隔符。
開始awk的使用
測試文件test.txt,\t分隔
$ cat test.txt
num name letter score
1 tom A 85
2 joy B 84
3 jack C 83
4 bob D 82
5 jerry E 81
輸出文件指定列
$ awk '{print $2,$3}' test.txt #默認\s或\t
name letter
tom A
joy B
jack C
bob D
jerry E
自定義分隔符-F
$ awk -F \s '{print $1}' test.txt #文件\t分隔,使用\s分隔
num name letter
1 tom A 85
2 joy B 84
3 jack C 83
4 bob D 82
5 jerry E 81
$ awk -F '\t' '{print $1}' test.txt
num
1
2
3
4
5
自定義變量 -v
$ awk -va=test '{print a,$1}' test.txt
test num
test 1
test 2
test 3
test 4
test 5
運算符
運算符 | 描述 |
---|---|
= += -= *= /= %= ^= **= | 賦值 |
?: | C條件表達式 |
|| | 邏輯或 |
&& | 邏輯與 |
~ ~! | 匹配正則表達式和不匹配正則表達式 |
< <= > >= != == | 關系運算符 |
空格 | 連接 |
+ - | 加,減 |
* / % | 乘,除與求余 |
+ - ! | 一元加,減和邏輯非 |
^ *** | 求冪 |
++ -- | 增加或減少,作為前綴或后綴 |
$ | 字段引用 |
in | 數組成員 |
比較表達式
$ awk '$2=="tom"' test.txt
1 tom A 85
$ awk '$4>82' test.txt
num name letter score
1 tom A 85
2 joy B 84
3 jack C 83
y$ awk '$4>82 {print $2}' test.txt
name
tom
joy
jack
conditional expression1 ? expression2: expression3
例如:$ awk '{max = {$1 > $3} ? $1: $3: print max}' test。
如果第一個域大于第三個域,1就賦值給max,否則3就賦值給max。
-
模式匹配
awk 'pattern {action}' test #對test中滿足pattern的行進行action
pattern
- 正則表達式://
- 關系表達式:可以用下面運算符表中的關系運算符進行操作,可以是字符串或數字的比較,如$2>%1選擇第二個字段比第一個字段長的行。
- 模式匹配表達式:用運算符(匹配)和!(不匹配)。
- 模式,模式:指定一個行的范圍。該語法不能包括BEGIN和END模式。
$ awk '$2 ~ /o/ {print $0}' test.txt #第二列匹配有字符o
1 tom A 85
2 joy B 84
4 bob D 82
$ awk 'BEGIN{IGNORECASE=1} /TOM/ {print $0}' test.txt #忽略大小寫
1 tom A 85
$ awk '$2~/j/ {print $0}' test.txt
2 joy B 84
3 jack C 83
5 jerry E 81
$ awk '$2!~/j/ {print $0}' test.txt
num name letter score
1 tom A 85
4 bob D 82
范圍模板
范圍模板匹配從第一個模板的第一次出現到第二個模板的第一次出現之間所有行。如$ awk '/root/,/mysql/' test將顯示root第一次出現到mysql第一次出現之間的所有行。
-
內建變量
變量 | 描述 |
---|---|
$n | 當前記錄的第n個字段,字段間由FS分隔 |
$0 | 完整的輸入記錄 |
ARGC | 命令行參數數目 |
ARGIND | 命令行中當前文件的位置(從0開始算) |
ARGV | 包含命令行參數的數組 |
CONVFMT | 數字轉換格式(默認值為%.6g) |
ENVIRON | 環境變量關聯數組 |
ERRNO | 最后一個系統錯誤的描述 |
FIELDWIDTHS | 字段寬度列表(用空格鍵分隔) |
FILENAME | 當前文件名 |
FS(Field Separator) | 輸入字段分隔符(默認空格 ) |
OFS (Out of Field Separator) | 輸出字段分隔符(默認空格) |
RS (Record Separator) | 輸入記錄分隔符(默認換行符), 默認將一行作為一條記錄,可整段讀取 |
ORS (Output Record Separate) | 輸出記錄分隔符(默認換行符) |
IGNORECASE | 如果為真,則進行忽略大小寫的匹配 |
FNR | 當前文件中的記錄號 |
NF(Number for Field) | 一條記錄的字段的數目 |
NR(Number of Record) | 多個文件,已經讀出的記錄數,就是行號,從1開始 |
OFMT | 數字的輸出格式(默認值是%.6g) |
RLENGTH | 由match函數所匹配的字符串的長度 |
RSTART | 由match函數所匹配的字符串的第一個位置 |
SUBSEP | 數組下標分隔符(默認值是/034) |
8 個有力的 Awk 內建變量這篇文章對常用的awk內建變量進行了總結,非常有用。
$ awk '{print ARGC,FILENAME,NR,FNR,$0}' test.txt
2 test.txt 1 1 num name letter score
2 test.txt 2 2 1 tom A 85
2 test.txt 3 3 2 joy B 84
2 test.txt 4 4 3 jack C 83
2 test.txt 5 5 4 bob D 82
2 test.txt 6 6 5 jerry E 81
-
awk編程:
awk 'BEGIN{最先執行的操作} {需要執行的命令或代碼} {需要執行的命令或代碼}' file
變量
awk內建變量:直接使用;
-v定義變量:-v var=val;
變量賦值并傳輸給awk腳本:如$ awk -F: -f awkscript month=4 year=2004 test,上式的month和year都是自定義變量,分別被賦值為4和2004。
BEGIN{最先執行的操作}
awk操作命令之前需要執行的語句;通常用來改變內建變量的值,如OFS,RS和FS等,以及打印標題。
$ awk 'BEGIN{FS=":"; OFS="\t"; ORS="\n\n"}{print $1,$2,$3} test。#在處理輸入文件以前,域分隔符(FS)被設為冒號,輸出文件分隔符(OFS)被設置為制表符,輸出記錄分隔符(ORS)被設置為兩個換行符。
$ awk 'BEGIN{print "TITLE TEST"} #打印標題。
{需要執行的命令或代碼}
END{最后執行的操作}
awk 'END{print "The number of records is" NR}' test,上式將打印所有被處理的記錄數。
例子:
$ vi test.awk
BEGIN{
print "---------------hello world!-------------\n"
}
{
printf "%15s %10s\n","I am writing:",$2
}
END{
print "---------------over!---------------\n"
}
運行程序:
$ awk -f test.awk test.txt
---------------hello world!-------------
I am writing: name
I am writing: tom
I am writing: joy
I am writing: jack
I am writing: bob
I am writing: jerry
---------------over!---------------
$ awk 'BEGIN{ print "Hello, world!"} {print "testing!"} END{print "over!"}' test.txt
Hello, world!
testing!
testing!
testing!
testing!
testing!
testing!
over!
awk條件語句
if語句
{if (condition){
action; action; ...
}
}
if/else語句
{if (condition){
action; action; ...
}
else{
action; action; ...
}
}
if/else else if
{if (condition){
action; action; ...
}
else if (condition){
action; action; ...
}
else if (condition){
action; action; ...
}
else {
action; action; ...
}
}
循環
while循環
{while(condition){
action
}
}
for循環
{for (i = 1; i<NF; i++)
}
{for(i in list){
action
}
}
awk的內建函數
字符串函數
sub() #字符串替換,發生在第一次匹配的時候;
sub(pattern,replace str)
sub(pattern,replace string, action range) #action range可以限定替換操作發生在文檔那些部分。
gsub() #字符串替換,將所有匹配進行替換操作;
gsub(pattern,replace str)
gsub(pattern,replace str, action range)
index() #返回字符串第一次被匹配的索引,起始為1
index(str, substr)
length() #返回字符串長度
length( str )
length #文件當前記錄字符串長度
substr() #截取字符串
substr( str, start)
substr( str, start, length)
match() #返回字符串匹配索引,失敗返回0;可以使用內建變量:RSTART(初始匹配index) RSTART(匹配字符串長度)
match( str, regular expression )
toupper()
toupper(str) #字符串轉換為大寫
tolower(str) #字符串轉換為小寫
split()
split( str, array,separator ) #按給定的分隔符把字符串分割為一個數組array
split( str, array)
時間函數
systime()
systime() #返回從1970年1月1日開始到當前時間(不計閏年)的整秒數。
自定義函數
function( parameter, parameter, parameter, ... ) {
statements
return expression
}
參考文獻: