AWK 腳本的結構
awk ' BEGIN{ print "start" } pattern { commands } END{ print "end" } file
awk 腳本通常由3部分組成。 BEGIN , END 和帶模式匹配選項的常見語句塊。這3個部分都是可 選項,在腳本中可省略任意部分。
AWK 腳本的執行
一、在命令行中執行 AWK 腳本
AWK 腳本包含在單引號之間
awk 'BEGIN { statements } { statements } END { end statements }'
二、把 AWK 腳本寫入文件
文件的內容格式如下
BEGIN { statements } { statements } END { end statements }
在命令使用如下命令執行腳本
awk -f <programfile> <inputfile>
programfile
: AWK 腳本文件inputfile
: 被處理的文件
AWK 的工作方式
一、AWK工作流程圖
Read
AWK從輸入流(文件,管道或者標準輸入)中讀取一行,然後存儲到內存中。
Execute
所有的AWK命令都依次在輸入上執行。默認情況下,AWK會對每一行執行命令,我們可以通過提供模式限制這種行爲。
Repeat
處理過程不斷重複,直到到達文件結尾。
二、AWK 執行流程
- 執行 BEGIN { commands } 語句塊中的語句。
- 從文件或 stdin 中讀取一行,然後執行 pattern { commands } 。重複這個過程,直到文件全部被讀取完畢。
- 當讀至輸入流末尾時,執行 END { commands } 語句塊。
三、要點理解
- BEGIN 語句塊在 awk 開始從輸入流中讀取行之前被執行。這是一個可選的語句塊,諸如變量 初始化、打印輸出表格的表頭等語句通常都可以寫入 BEGIN 語句塊中。
- END 語句塊和 BEGIN 語句塊類似。 END 語句塊在 awk 從輸入流中讀取完所有的行之後即被執 行。像打印所有行的分析結果這類彙總信息,都是在 END 語句塊中實現的常見任務(例如,在比 較過所有的行之後,打印出最大數)。它也是一個可選的語句塊。
- 最重要的部分就是 pattern 語句塊中的通用命令。這個語句塊同樣是可選的。如果不提供該 語句塊,則默認執行 { print } ,即打印所讀取到的每一行。 awk 對於每一行,都會執行這個語 句塊。這就像一個用來讀取行的 while 循環,在循環體中提供了相應的語句。
- 每讀取一行, awk 就會檢查該行和提供的 pattern 是否匹配。pattern 本身可以是正則表達式、條件 語句以及行匹配範圍等。如果當前行匹配該 pattern ,則執行 { } 中的語句。
- pattern 是可選的。如果沒有提供樣式,那麼 awk 就認爲所有的行都是匹配的,並執行 { } 中的 語句
AWK 的一些特殊變量
-
NR :表示記錄數量,在執行過程中對應於當前行號。
-
NF :表示字段數量,在執行過程中對應於當前行的字段數。
-
$0 :這個變量包含執行過程中當前行的文本內容。
-
$1 :這個變量包含第一個字段的文本內容。
-
$2 :這個變量包含第二個字段的文本內容。
-
$ awk '{ print $3,$2 }' file #打印每一行的第2和第3個字段:
-
$ awk 'END{ print NR }' file #統計文件中的行數
將外部變量值傳遞給 AWK
藉助選項 -v
,我們可以將外部值(並非來自 stdin )傳遞給 awk
$ VAR=10000
$ echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
10000
用 getline 讀取特定行:
awk 通常默認讀取一個文件的所有行。如果只想讀取某一行,可以使用 getline 函數。有時候,我們需要從 BEGIN 語句塊中讀取第一行。
語法: getline var
變量 var 就包含了特定行的內容。如果調用不帶參數的 getline ,我們可以用 $0
、 $1
和 $2
訪問文本行的內容。
$ seq 5 | awk 'BEGIN { getline; print "Read ahead first line", $0 } { print $0 }'
Read ahead first line 1
2
3
4
5
使用過濾模式對 AWK 處理的行進行過濾:
$ awk 'NR < 5' # 行號小於5 的行
$ awk 'NR==1,NR==4' # 行號在1 到5 之間的行
$ awk '/linux/' # 包含樣式linux 的行(可以用正則表達式來指定模式)
$ awk '!/linux/' # 不包含包含模式爲linux
設置字段定界符:
默認的字段定界符是空格。我們也可以用 -F "delimiter" 明確指定一個定界符
$ awk -F: '{ print $NF }' /etc/passwd
在 BEGIN 語句塊中則可以用 OFS="delimiter"
設置輸出字段的定界符。
從 AWK 中讀取命令輸出:
將命令的輸出結果讀入變量 output 的語法如下
"command" | getline output ;
$ echo | awk '{ "grep root /etc/passwd" | getline cmdout ; print cmdout }'
root:x:0:0:root:/root:/bin/bash
通過使用 getline ,我們將外部shell命令的輸出讀入變量 cmdout 。
在 AWK 中可以使用 for 循環,其格式如下:
for(i=0; i<10; i++) { print $i ; }
或者
for(i in array) { print array[i]; }
AWK 內建的字符串控制函數
- length(string) :返回字符串的長度。
- index(string, search_string) :返回 search_string 在字符串中出現的位置。
- split(string, array, delimiter) :用定界符生成一個字符串列表,並將該列表存 入數組。
- substr(string, start-position, end-position) :在字符串中用字符起止偏移 量生成子串,並返回該子串。
- sub(regex, replacement_str, string) :將正則表達式匹配到的第一處內容替換 成 replacment_str 。
- gsub(regex, replacment_str, string) :和 sub() 類似。不過該函數會替換正則表 達式匹配到的所有內容。
- match(regex, string) :檢查正則表達式是否能夠匹配字符串。如果能夠匹配,返回 非0值;否則,返回0。