1. 程式人生 > >shell指令碼之awk

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函式重新讀取出來。