1. 程式人生 > >Linux Shell程式設計 awk命令

Linux Shell程式設計 awk命令

概述

awk是一種程式語言,用於在linux/unix下對文字和資料進行處理。資料可以來自標準輸入(stdin)、一個或多個檔案,或其它命令的輸出。它支援使用者自定義函式和動態正則表示式等先進功能,是linux/unix下的一個強大程式設計工具。它在命令列中使用,但更多是作為指令碼來使用。awk有很多內建的功能,比如陣列、函式等,這是它和C語言的相同之處,靈活性是awk最大的優勢。

命令的基本格式如下:

[[email protected] ~]# awk '條件1 {執行語句 1} 條件 2 {執行語句 2} …' 檔名

在awk程式設計中,因為命令語句非常長,所以在輸入格式時需要注意以下內容:

  • 多個條件{動作}可以用空格分隔,也可以用回車分隔。
  • 在一個動作中,如果需要執行多條命令,則需要用分隔,或用回車分隔。
  • 在awk中,變數的賦值與呼叫都不需要加入"$"符號。

條件(Pattern):
一般使用關係表示式作為條件。這些關係表示式非常多 。

條件型別 條 件 說 明
awk保留字 BEGIN 在 awk 程式一開始,尚未讀取任何資料之前執行。BEGIN 後的動作只在程式開始時執行一次
awk保留字 END 在 awk 程式處理完所有資料,即將結束時執行?END 後的動作只在程式結束時執行一次
關係運算符 > 大於
< 小於
>= 大於等於
<= 小於等於
== 等於。用於判斷兩個值是否相等。如果是給變童賦值,則使用"=”
!= 不等於
A~B 判斷字串 A 中是否包含能匹配 B 表示式的子字串
A!~B 判斷字串 A 中是否不包含能匹配 B 表示式的子字串
正則表示式 /正則/ 如果在“//”中可以寫入字元,則也可以支援正則表示式

awk常見的內建變數 

awk 內建變數

說明
$0 當前記錄(作為單個變數)
$1~$n 當前記錄的第n個欄位,欄位間由FS分隔
FS 輸入欄位分隔符, 預設為空白字元
OFS 輸出欄位分隔符, 預設為空白字元
RS 輸入記錄分隔符(輸入換行符), 指定輸入時的換行符
ORS 輸出記錄分隔符(輸出換行符),輸出時用指定符號代替換行符
NF 當前行的欄位的個數(即當前行被分割成了幾列),欄位數量
NR 當前處理的文字行的行號 
FNR 各檔案分別計數的行號
FILENAME 當前檔名
ARGC 命令列引數的個數
ARGV 陣列,儲存的是命令列所給定的各引數

awk命令示例

awk命令基本示例

列出 student.txt 檔案的第二個欄位和第六個欄位,"$2"和"$6"分別代表第二個欄位和第六個欄位。

[[email protected] ~]# awk '{printf $2 "\t" $6 "\n"}' student.txt
#輸出第二列和第六列的內容
Name Average
Liming 87.66
Sc 85.66
Gao 91.66

對於 awk 命令來說,只要分隔開,不管是空格還是製表符,都可以識別。 命令如下:

[[email protected] ~]#df -h | awk '{print $1 "\t" $3}'
檔案系統 已用
/dev/sda3 1.8G
tmpfs 0
/dev/sda1 26M
/dev/sr0 3.5G

在這兩個例子中,如果使用 printf 動作,就必須在最後加入"\n",因為 printf 只能識別標準輸出格式;如果我們不使用"\n",它就不會換行。而 print 動作則會在每次輸出後自動換行,所以不用在最後加入"\n"。

awk使用條件的示例

BEGIN 是 awk 的保留字,是一種特殊的條件型別。BEGIN 的執行時機是"在 awk 程式一開始,尚未讀取任何資料之前"。一旦 BEGIN 後的動作執行一次,當 awk 開始從檔案中讀入資料時,BEGIN 的條件就不再成立,所以 BEGIN 定義的動作只能被執行一次。例如:

[[email protected] ~]# awk 'BEGIN{printf "This is a transcript\n"}
{printf $2 "\t" $6 "\n"}' student.txt
This is a transcript
Name Average
Liming 87.66
Sc 85.66
Gao 91.66

awk命令只要檢測不到完整的單引號就不會執行,所以這條命令的換行不用加入"\",就是一行命令。首先使用BEGIN條件在讀入檔案資料前列印"這是一張成績單"(只會執行一次),再列印檔案的第二個欄位和第六個欄位。

END 是在 awk 程式處理完所有資料,即將結束時執行的。END 後的動作只在程式結束時執行一次。例如:

[[email protected] ~]# awk 'END{printf "The End \n"}
{printf $2 "\t" $6 "\n"}' student.txt
Name Average
Liming 87.66
Sc 85.66
Gao 91.66
The End

 檢視平均成績大於等於 87 分的學員,就可以這樣輸入命令:

[[email protected] ~]# cat student.txt | grep -v Name |awk'$6 >= 87 {printf $2'\n"}'
Liming
Gao

使用cat輸出檔案內容,用grep取反包含"Name"的行
判斷第六個欄位(平均成績)大於等於87分的行,如果判斷式成立,則列印第2列學員名

檢視Sc使用者的平均成績

[[email protected] ~]# awk'$2 -/Sc/ {printf $6 "\n"}' student.txt
85.66

如果第二個欄位中包含"Sc"字元,則列印第六個欄位

在 awk 中,只有使用"//"包含的字串,awk 命令才會査找。也就是說,字串必須用"//"包含,awk 命令才能正確識別。

査看系統分割槽的使用情況而不想査看光碟和臨時分割槽的使用情況時,可以只查詢包含"sda數字"的行,並列印第一個欄位和第五個欄位

[[email protected] ~]# df -h | awk '/sda[0-9]/ {printf $1 '\t\ $5 "\n"}'
/dev/sda3 10%
/dev/sda1 15%

awk使用內建變數的示例

在 awk 中允許定義變數,允許使用運算子,允許使用流程控制語句和定義函式。這樣就使得 awk 程式設計成了一門完整的程式語言,當然難度也比普通的命令要大得多。

建立檔案

[[email protected] ~]# cat student.txt
ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66

在 awk 中定義變數與呼叫變數的值。假設統計 PHP 成績的總分:

[[email protected] ~]# awk'NR==2{php1 =$3}
NR==3{php2=$3}
NR==4{php3= $3;totle=php1+php2+php3;print "totle php is" totle}' student.txt
totle php is 255

說明:

  • "NR==2{php1=$3}"(條件是NR==2,動作是php=$3) 是指如果輸入資料是第二行(第一行是標題行),就把第二行的第三個欄位的值賦予變數"php1"。
  • "NR==3{php2=$3}"是指如果輸入資料是第三行,就把第三行的第三個欄位的值賦予變數"php2"。NR==4{php3=$3;totle=php1+php2+php3;print"totle php is"totle}"("NR==4"是條件,後面{}中的都是動作)是指如果輸入數是第四行,就把第四行的第三個欄位的值賦予變數"php3";然後定義變數 totle 的值是"php1+php2+php3";最後輸出"totle php is"關鍵字,後面加變數 totle 的值。

檢視Linux 成績大於 90 分的使用者,命令如下:

[[email protected] ~]# awk' NR>=2 {test=$4}
test>90 {printf $2" \n"}' student.txt
Liming
Sc

先判斷行號,如果大於2,就把第四個欄位的值賦予變數test

再判斷成績,如果test的值大於90分,就列印好男人