Linux 伺服器系統管理第十二章 Sed 與 awk 處理工具  上一頁    下一頁

12-3 Awk 搜尋敘述與動作

內容:

12-3 awk 處理程式的概念圖,其指令格式為 ‘statement {action}’,其中包含搜尋條件敘述與處理動作。開始執行時,awk 依序由輸入檔案每次讀取一行(一筆記錄),經由搜尋敘述檢蒐是否符合條件,如果不符合則放棄該行,並繼續搜尋下一行;如果符合條件的話,則經由指定『動作』處理後,再選擇是否輸出到其他檔案或螢幕。以下將介紹 awk 有哪些搜尋敘述與處理動作。

 

12-3 Awk 的處理程式

12-3-1 Awk 搜尋敘述

Awk 搜尋方法比 sed 活用許多,sed 是以串流方式經過檢蒐器,而 awk 可以前後搜尋該行多次,因此 awk 的搜尋敘述會複雜許多,但也不會偏離以下搜尋敘述太多(每一版本的搜尋敘述並非完全相同):

Ø  字串搜尋:搜尋某一符合字串的敘述,可以使用明文表示,也可用正規式表示某一圖樣空間(pattern space)的文字。

Ø  比較符號:比較兩個元素的敘述,可以大於(>)、大於等於(>=)、小於(<)、小於等於(<=)、相等(==)、不相等(!=)等等。比較元素可以是某一指定變數或該筆記錄的欄位內容,比較內容也可以是字串或數值。

Ø  結合運算:超過兩個以上的比較敘述,可利用『且』(and&&)、『或』(or||)或『否』(not!)將其結合成一個條件敘述。

Ø  指定範圍:可以指定某一範圍的敘述,搜尋兩個指定的邊界之間的文字或數字。

Ø  BEGIN END 敘述組合BEGIN 是指定 awk 處理程式之前所需執行的某些敘述;END awk 處理後,再繼續處理的一些後續敘述。

接下來,我們用一些簡單範例來驗證以上的搜尋敘述。

A. Awk 字串搜尋範例】

salary 檔案(前一小節的範例)中搜尋,是否有 Nacy 字樣的記錄,如有則印出該記錄內容,操作範例如下:

[tsnien@Linux-1 tools]$ awk '/Nacy/ { print }' salary

Nacy    51      70000   06-2851178

B. Awk 比較符號範例】

列印出年齡小於 50 歲員工的姓名、年齡與薪資(由 salary 檔案),操作如下:

[tsnien@Linux-1 tools]$ awk '$2 <50 {print $1, "\t", $2, "\t", $3}' salary

Frank    30      40000

George   48      50000

Louis    42      65000

C. Awk 結合運算範例】

列印出年齡小於 50 歲而且薪資高於或等於 50000 元員工的姓名與電話。

$ awk '($2 <50) && ($3 >= 50000) {print $1, "\t", $4}' salary

George   07-4553211

Louis    04-3298101

D. Awk 指定範圍範例】

列印出薪資介於 50000 70000 員工的資料。

[tsnien@Linux-1 tools]$ awk '/50000/, /70000/ {print}' salary

George  48      50000   07-4553211

Nacy    51      70000   06-2851178

其實,上述範例並非僅比較薪資欄位,awk 每讀取一筆資料,都會比較所有欄位,如果任一欄位內容符合條件的話,則印出該筆資料的內容;由此可見,採用指定範圍搜尋,必須先了解記錄內各欄位資料是否有相似的地方,如有的話,則必須指明比較哪一個欄位的內容。

E. Awk BEGIN/END 敘述範例】

列印出年齡大於 40 歲員工的姓名,搜尋之前先印出一行 “******”,搜尋完成之後在印出一行 “=====”,範例如下:

$ awk 'BEGIN {print "****"} $2 >40 {print $1} END {print "====="}' salary

****

George

Nacy

Louis

=====

12-3-2 Awk 指定動作

基本上,awk 是以『行』(記錄)為單位做搜尋處理,符合搜尋條件之後,指定動作也是針對『行』處理。但並非完全如此,記錄之間或許需要做整合處理的工作,如此一來 awk 的指定動作就顯然會複雜許多。本節先來介紹 awk 的基本指定動作,但當單一命令行無法得到滿意的結果時,也許需要將這些指定動作編寫成命令稿方式,這部份保留到下一節再說明。

A. 自定與內建變數】

如同其他程式語言一樣,除了保留字集特殊符號外,都可作為變數名稱。自定變數不用宣告就可直接使用,如 price=30。變數內容可以是數值或文字字串,而且可以經由運算(數學或比較運算)得到另一個變數的結果。Awk 也保留了一些內建變數,如下表 12-4 所示。

12-4 Awk 內建變數

變數名稱

意義

FS

輸入欄位分隔字元

OFS

輸出欄位分隔字元

NF

記錄(行)的欄位數量

NR

目前記錄(行)的筆數

FILENAME

輸入檔案名稱

FNR

目前檔案的記錄數目

ARGC

命令列參數的數目

ARGV

命令列參數陣列

另外,每筆資料中有用特殊變數名稱來表示欄位位置,譬如,$1 為第一個欄位、$2 是第二個欄位……等等,並且以 $0 做為該筆資料的所有欄位資料。

B. 數值運算與函數】

早期 awk 是在 Unix 系統上發展出來的,一般 C 語言所具有的數值運算式與函數,awk 大致上都有,如下所示:

Ø  基本運算式:包含有指定(=)、加(+)、減(-)、乘(*)、除(/)、取餘數(%)、指數(^)等運算式。

Ø  指定運算式:包含有:+=-=*=/=%=、以及 ^= 等運算式。

Ø  遞增與遞減運算:遞增運算式為 ++;遞減為 --

Ø  內定函數: sin()cos()、以及 rand() 等等數學函數。

C. 陣列】

Awk 並不使用宣告或定義方式來產生陣列,而是為每一個陣列元素獨立設定某一數值,再自動將這些元素連結而成。另一方面,awk 陣列是屬於關聯陣列(associative array),其索引值是使用字串型態,而非數值型態。操作方式如下:

Ø  指定陣列:產生並指定某一數值給一個陣列,如 stack[1] = $2,表示將第二個欄位指定到 stack 陣列的第一個元素中。

Ø  使用陣列:將陣列中內容取出,如 stack[1]++,表示 stack 陣列第一個元素遞增。

Ø  字元索引陣列:利用字元索引陣列,如 count[“display”] = 5

D. 自定函數】

Awk 允許使用者自定函數,語法如下:

function function_name(list of parameter) { action_list}

其中,function_name 為自定函數的名稱,傳遞參數不用宣告變數型態,又利用左右大括號({…..})表示函數實體範圍。自定一個遞迴函數(fact())的範例如下:

function fact(k) {

if (k <= 1)

   return 1

else

    Return k * fact(k-1)

}

呼叫自定函數的語法如下:(以 fact() 函數為例)

value = fact(5)

E. 內建函數】

Awk 的內定函數,可區分為以下兩大類:

²  內建算數函數:如同一般程式語言,有 cos(x)(餘弦函數,x 為弧度數值)、exp(x)x 的指數值)、int(x)(最接近 x 的整數值)、log(x)x 的自然對數值)、sin(x)x 的正弦值)、sqrt(x)x 的平方根值)、atan2(x, y)x/y 的反正切值)、rand()0 <r <1 之間的亂數)、以及 srand(x)x rand() 的亂數種子)等。

²  內建字串函數:畢竟處理字串(或圖樣)才是 awk 最得手的工作,字串函數的功能也與其他語言相差甚多,我們將較常用的內建字串函數歸納成表 18-2

18-2 Awk 內建字串函數

Awk 函數

功能說明

gsub(r, s, t)

在字串 t 中,所有(global)與正規式 r 相似的地方,都將它取代成 s;如沒有指定 t,則內定值為 $0

index(s, t)

回傳字串 t 在字串 s 首次出現的位置,如沒有則回傳 0

length(s)

回傳字串 s 的長度,如沒有指定,則內定值為 $0

match(s, r)

回傳在字串s中,與 s 正規式符合字串的起始位置;沒有相符則回傳 0

split(s, a, sep)

sep 為欄位分隔記號,將字串s分割並存入陣列 a 之中;如無指定 sep,則以系統 FS 取代。

sub(r, s, t)

在字串 t 中,第一個與正規式 r 相似的地方,都將它取代(substitute)成 s;如沒有指定 t,則內定值為 $0

substr(s, p, n)

回傳一個子字串,在字串s中自位置 p 開始,最大長度為 n 的子字串。

tolower(s)

將所有字串s中所字母改變成小寫字母。

toupper(s)

將字串s字母改變成大寫字母。

 

翻轉工作室:粘添壽

 

Linux 伺服器系統管理 - CentOS:

 

 

 

翻轉電子書系列: