shell指令碼之awk
(一) 什麼是awk
awk其實相當於一門可以處理資料文字的語言,這麼說的原因是其具有很多類c語言的語法,如:變數,陣列,函式,流程控制等,其由Aho,Weinberger,Kernighan大約在1977年開發完成,隨後被引入unix/linux中。
(二) awk可以幹什麼
awk是一個非常強大的資料處理工具,可對文字進行的編輯,篩選,其非常適用於處理有行和列組成的文字資料,就像處理資料庫中的記錄一樣,可以刪除列,新增列或者刪除行,修改行與新增行等一系列操作,非常實用。
(三)awk的基本語法
一般形式:awk pattern {actions} filename
- 【pattern】:表示匹配模式。
- 【{action}】:要執行的操作
說明:以上語法表示當某個問本行負符合pattern指定的匹配規則時,執行action操作。
注意:以上pattern與{actions}是可選的,但是必須有其中一個,並且action前面的左大括號需要與pattern位於同一行中,尼瑪,我就吃過這一次虧,特此強調。
(四) 執行awk程式的幾種方式
(1)通過命令執行awk程式
例如:
awk ‘{print}’ filename 輸出filenam全部的資料
awk ‘/^T/ {print} ’ filename 輸出行首為T的文字行
(2)通過awk指令碼
例如:
把awk ‘/^T/ {print} ’ filename 中的’/^T/ {print} ‘寫入test文字檔案中,然後執行**awk -f test filename 就達到和上述一樣的效果了。
(3)通過可執行程式
例如:
直接將 awk ‘/^T/ {print} ’ filename寫入指令碼檔案test.awk中如下:
#! /usr/bin/awk -f
'/^T/ {print} '
賦予該指令碼可執行許可權後,執行:./test.awk filename 就OK.
(五) awk的模式匹配,即pattern中可以使用的形式
(1)關係表示式,既可以使用> ,< ,== ,!=等關係表示式作為匹配模式,進行篩選。
例如:
awk ‘$2>80 {print}’ filename 顯示第二列大於80的行。
(2)正則表示式,既可以使用[$,.,^,* ,[]]等正則表示式作為匹配模式,進行篩選。
例如:
#! /usr/bin/bash
result=`awk '/^T/ {print}' filename `
result=`awk '/^(Tom|Key)/ {print}' filename `
echo $result
(3)混合模式,即既可以使用關係表示式又可以使用正則表示式進行混合。
例如:
#! /bin/bash
result=`awk '/^T/ && $2 > 80 {print}' filename `
echo $result
(4)區間模式,通過條件匹配一段連續的問本行。
例如:
#! /bin/bash
#匹配/^Tom/與$2=90行之間的行
result=`awk '/^Tom/,$2=90 {print}' filename `
echo $result
(5)BEGIN模式
該模式是一種特殊的你內建模式,執行於awk程式還沒有讀取文字行之前,該模式僅僅被執行一次,當awk讀取資料以後BEGIN不再成立。
例如:
#! /usr/bin/awk -f
#輸出字串
BEGIN{ print "hello world!"}
又如:
#! /usr/bin/awk -f
#可以在開始執行awk前定義變數並進行一系列的初始化工作
BEGIN{
FS="[\t:]"
RS="\n"
count=30
print RS count
}
(6)END模式
該模式是一種特殊的你內建模式,執行於awk程式讀取文字行並處理完以後,即將推出程式是執行,相當於做善後操作,該模式所對應的操作只執行一次。
例如:
#! /usr/bin/awk -f
#程式退出時顯示提示資訊
END{
print "code end"
}
(六) awk提供的系統函式
- index(str1,str2):返回str2在str1中的位置,如果有多個匹配,則返回第一個位置,否則返回0。
- length(str) :字串長度
- split(str,arr,seperator):以seperator為分隔符把str分割存入陣列arr中
- match(str,regexp):在str中搜索符合正則表示式regex的子字串。
- sub(regexp,replace,str):將str中第一個符合正則表示式regexp的子字串替換為replace。
- gsub(regexp,replace,str):將str中全部符合正則表示式regexp的子字串替換為replace。
- substr(str,start,length):將字串str中擷取指定的子字串。
- 算術函式 想了解的自己查吧,這個太囉嗦。
(七) awk的流程控制
(1)判斷
if(exp)
{
statement
...
}
else
{
statement
...
}
(2)迴圈
for(i=0; i<n;i++)
{
statement
...
}
或
while( exp )
{
statement
...
}
或
do
{
statement
...
}while( exp );
(3)控制
- break
- continue
- next 和cotinue不同,next並不用在迴圈結構中,而是用在整個awk中,當awk執行程式時,如果遇到next語句,則該語句中所有的程式語句都被忽略,awk則會讀取下一行資料,並且從第一個模式及操作開始執行。
例如:
#! /usr/bin/awk -f
##當讀取的行為空行時,跳過後面的語句
/^[\t]*$/{
next
}
{
print $1,$2,$3,$4
}
- exit
(八) awk的格式化輸出
(1)print
(2)priint(“format”,num);
(3)sprintf(“format”,num):sprintf()函式的功能與prntf()函式大致相同,但是該函式只是以字串的形式返回格式化結果,並不輸出到標準裝置。可以使用該函式的返回結果使用print,printf()輸出到標準裝置上。
#! /usr/bin/awk -f
BEGIN{
print "begin"
total=0
}
{
printf("%s\t%d\t%d\t%d\t\n",$1,$2,$3,$4)
total=total+$2+$3+$4
}
END{
##計算平均分
ave=total/NR
##輸出統計結果
sum=sprintf("Total:%d stutents,ave:%0.2f",NR,ave);
print sum
}
(九) awk與shell的互動使用
(1)通過管道實現與shell的交換
例如:
#! /usr/bin/awk -f
BEGIN{
#通過管道來執行who命令的執行結果
while("who" | getline )
{
i++
}
printf("there are %d online users",n)
}
上述例子中,通過管道來執行who命令,將執行結果傳遞給getline函式,該函式依次讀取每一行資料
(2)通過system函式實現與shell的互動
例如:
#! /usr/bin/awk -f
BEGIN{
system("ls > filename")
while( getline < "filename" > 0 )
{
print $1
}
}
上述例子中,使用system函式執行ls命令,由於system 不支援函式的傳遞,所以必須將結果重定向到filename檔案中,然後用getline函式重新讀取出來。