1. 程式人生 > >文本處理三劍客之awk(原創)

文本處理三劍客之awk(原創)

創建 兩個 位置 正則 ack 最大 align common 因此

文本處理三劍客之awk(原創)

AWK是一種優良的文本處理工具,LinuxUnix環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操作語言(其名稱得自於它的創始人阿爾佛雷德·艾侯(Alfred Aho)、彼得·溫伯格(Peter Jay Weinberger)和布萊恩·柯林漢(Brian Wilson Kernighan)姓氏的首個字母)的最大功能取決於一個人所擁有的知識。AWK提供了極其強大的功能:可以進行正則表達式的匹配,樣式裝入、流控制、數學運算符、進程控制語句甚至於內置的變量和函數。它具備了一個完整的語言所應具有的幾乎所有精美特性。實際上AWK的確擁有自己的語言:AWK程序設計語言,三位創建者已將它正式定義為“樣式掃描和處理語言”。它允許您創建簡短的程序,這些程序讀取輸入文件、為數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。

gawkAWKGNU版本。最簡單地說,AWK是一種用於處理文本的編程語言工具。AWK在很多方面類似於Unix shell編程語言,盡管AWK具有完全屬於其本身的語法。它的設計思想來源於SNOBOL4sedMarc Rochkind設計的有效性語言、語言工具yacclex,當然還從C語言中獲取了一些優秀的思想。在最初創造AWK時,其目的是用於文本處理,並且這種語言的基礎是,只要在輸入數據中有模式匹配,就執行一系列指令。該實用工具掃描文件中的每一行,查找與命令行中所給定內容相匹配的模式。如果發現匹配內容,則進行下一個編程步驟。如果找不到匹配內容,則繼續處理下一行。

在我們的Linux中,awk其實是

gawk的一個軟連接,所以我們所使用的都是GNU AWK

技術分享圖片

技術分享圖片

awk的運行方式:

(1) awk命令行

# awk

(2) awk程序文件

# awk -f /path/from/awk_script

(3) awk腳本

#!/bin/awk –f

Awk在處理文本時會將每一行讀取到自己的內存空間當中,並將每一行文本根據我們制定的分隔符等分成不同的區域,類似腳本的內置位置變量。在處理完之後,輸出時awk依然是按照一行來輸出的,即便是輸出的內容不是原來的一整行,輸出的分割符默認為空格,也可以自定義。

技術分享圖片

技術分享圖片

基本用法:

gawk [OPTIONS] 'program' FILE1 FILE2 ...

program: PATTERN{ACTION STATEMENT}

由語句組成,各語句間使用分號分隔;

ACTION: print, printf

選項:

-F[]: 指明輸入字段分隔符,可以是多個,例:-F [:,]即用:當分隔符又用,當分隔符;

-v VAR_NAME=VALUE: 變量賦值;

-f /PATH/FROM/AWK_SCRIPT

技術分享圖片

技術分享圖片

技術分享圖片

1awk的輸出命令之一:print

用法:print item1, item2, ...

item

字符串:用引號引用;

print "hello", "world"

變量:顯示變量的值;

print name

引用變量:直接使用變量名

數值:無須加引號

要點:

(1) item之間需要使用逗號分隔;而輸出時的分隔符為默認為空白字符;

(2) 輸出的各item可以為字符串或數值、當前記錄的字段($#)、變量或awk的表達式;數值會被隱式轉換為字符串進行輸出;

(3) print後面的item省略時,相當於運行“print $0”,用於輸出整行;

(4) 輸出空白字符:print " "

2、變量

內建變量,自定義變量

2.1 內置變量

AWK的內建變量包括域變量,例如$1, $2, $3,以及$0。這些變量給出了記錄中域的內容。 內建變量也包括一些其他變量:

NR:已輸入記錄的條數。

FNR:行數,各文件單獨計數。

NF:當前記錄中域的個數。記錄中最後一個域可以以$NF的方式引用。print NF 每行有幾個字段,print $NF 顯示每一行的最後一個字段

FILENAME:當前輸入文件的文件名。

FS:“域分隔符”,用於將輸入記錄分割成域。其默認值為“空白字符”,即空格和制表符。FS可以替換為其它字符,從而改變域分隔符。-v FS="[ ,:.]"

RS:當前的“記錄分隔符”。默認狀態下,輸入的每行都被作為一個記錄,因此默認記錄分隔符是換行符。

OFS:“輸出域分隔符”,即分隔print命令的參數的符號。其默認值為空格。

ORS:“輸出記錄分隔符”,即每個print命令之間的符號。其默認值為換行符。

OFMT:“輸出數字格式”(Format for numeric output),其默認值為"%.6g"

ARGCawk命令行中的參數的個數。

ARGV:數組,保存了命令行參數本身。

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

2.2 自定義變量

(1) -v VAR_NAME=VALUE

變量名區分字符大小寫;

(2) program中自定義變量

# awk 'BEGIN{FS=":";f1=3}{print $f1}' /etc/passwd

技術分享圖片f1賦值一次一直使用

技術分享圖片每讀取一行f1賦一次值

3awk的輸出命令之二:printf

語法:printf FORMAT(格式),item1,item2,...

要點:

(1) 必須提供FORMAT

(2) print語句不同,printf不會自動換行,需要顯式指定換行符:\n

(3) FORMAT中需要分別為後面的每個item指定一個格式符,否則item則無法顯示;

格式符:都以%開頭,後跟單個字符;

%c: 顯示字符的ASCII碼;

%d, %i:顯示為十進制整數;

%e, %E: 科學計數法顯示數值;

%f:顯示為浮點數;

%g, %G:以科學計數法或浮點數格式顯示數值;

%s: 顯示為字符串;

%u:顯示無符號整數;

%%: 顯示%符號自身;

技術分享圖片

修飾符:

#[.#]

左邊的#:用於指定顯示寬度;

右邊的#: 顯示精度;

+:顯示數值符號

-:左對齊

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

4、操作符

算術操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x: 負值

+x: 轉換為數值

字符操作符:字符串連接

賦值操作符:

=, +=, -=, *=, /=, %=, ^=

++, --

比較操作符:

>, >=, <, <=, ==, !=

模式匹配操作符:

~:是否能由右側指定的模式所匹配;

!~:是否不能由右側指定模式所匹配;

邏輯操作符:

&&:與運算

||: 或運算

條件表達式:

selector?if-true-expression:if-false-expression

# awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or Sysuser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd

函數調用:

function_name(argu1, argu2, ...)

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

5PATTERN模式

(1) empty:空模式,匹配所有行;

(2) /Regular Expression/(正則表達式):僅將ACTION應用於能夠被Regular Expression所匹配到的行;

例如:awk -F: '/^[ab]/{print $1,$3}' /etc/passwd

技術分享圖片

(3) relational expression:關系表達式,即結果為“真”、“假”的表達式, 或者其結果能類同於“真”或“假”的表達;一般來說,其結果為非0數值或非空字符串即可類同為“真”,否則,則類同為“假”;

例如:awk -F: '$3>=500{print $1,$3}' /etc/passwd

技術分享圖片

例如:awk -F: '$1~/root/{print $1,$3}' /etc/passwd

技術分享圖片

(4) line ranges:行範圍,類似sedvim中的地址定界方式

startline,endline

此方式我沒有試驗成功,待定

(5) BEGIN/END:兩個特殊模式

BEGIN:在文件格式化操作開始之前事先執行的一次操作;通常用於輸出表頭或做出一個預處理操作;

END:在文件格式操作完成之後,命令退出之前執行的一次操作;通常用於輸出表尾或做出清理操作;

技術分享圖片

技術分享圖片

6、常用ACTION

(1) EXPRESSIONS:例如變量賦值

(2) Control Statements:控制語句,如if, while等;

(3) Compound Statements:復合語句

(4) input statements:輸入語句

(5) output statements:輸出語句

7、控制語句

if (condition) { statements } [else { statement }]

while (condition) { statements }

do statement while (condition)

for(expr1;expr2;expr3) { statements }

for(var in array) { statements }

switch (expression) {case VALUE or /REGEXP/: statement; ...; default: statementN}

break

continue

delete array[index]

delete array

exit [ expression ]

{ statements }

7.1 if-else

語法:if (condition) statement [ else statement ]

if (condition) {statements} [else {statements}]

~]# awk -F: '{if ($3>=500) print $1,$3}' /etc/passwd

~]# awk '{if (NF>=6) print NF,$0}' /etc/rc.d/rc.sysinit

~]# awk -F: '{if ($3>=500) {print $1,"is a common user"} else {print $1,"is a sysadmin or sysuser"}}' /etc/passwd

使用場景:對awk取得的整行或行中的字段做條件判斷;

技術分享圖片

技術分享圖片

7.2 while循環

語法:while (condition) statement

while (condition) {statements}

條件為“真”時循環,為“假”時退出循環;

使用場景:通常用於在當前行的各字段間進行循環;

~]# awk '{i=1;while(i<=NF){if (length($i)>=6) {print $i};i++}}' /etc/issue

技術分享圖片

7.3 do-while循環

語法:do statement while (condition)

do {statements} while (condtion)

意義:至少執行一次循環體

7.4 for循環

語法:for (expr1;expr2;expr3) statement

for (expr1;expr2;expr3) {statements}

for (variable assignment;codition;iteration process) {for-body}

# awk '{for(i=1;i<=NF;i++){if(length($i)>=6) print $i}}' /etc/issue

技術分享圖片

第二種用法:用於遍歷數組中的元素

for (var_name in array) {for-body}

7.5 swtich

語法:switch (expression) {case VALUE or /REGEXP/: statement; ...; default: statementN}

7.6 break and continue

break [n]:退出當前循環,n是一個數字,用於指定退出幾層循環;

continue:提前結束本輪循環而進入下一輪;

7.7 next

提前結束對本行文本的處理,而提前進入下一行的處理操作;

~]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd

技術分享圖片

8、數組

關聯數組:array[index-expression]

index-expression

可以使用任意字符;

如果某數組元素事先不存在,則在引用時,awk會自動創建此元素並將其值初始化為空串;

因此,若要判斷 數組中的某元素是否存在,要使用“index in array”的方式進行判斷;

要遍歷數組中的元素,則要使用for (var_name in array)的方式進行;此時,var_name會遍歷array的每個索引,所以,要顯示數組元素的值,要使用array[var_name]

weekdays

weekdays[mon]="Monday"

weekdays[tue]="Tuesday"

...

for (i in weekdays):此時,i變量會遍歷weekdays數組的每個索引,即mon, tue,而非元素的值“Monday”或"Tuesday"等;

要獲取元素的值:weekdays[i]

技術分享圖片

技術分享圖片

技術分享圖片

9、函數

內建函數和用戶自定義函數

9.1 內建函數

數值處理:

rand():返回01之間的一個隨機數;

技術分享圖片

字符串處理:

length([s]):返回指定的字符串的長度;

技術分享圖片

sub(r,s[,t]):基於r所表示的模式來匹配字符串t中的內容,將其第一次被匹配到的內容替換為s所表示的字符串;

技術分享圖片

gsub(r,s[,t]):基於r所表示的模式來匹配字符串t中的內容,將其所有被匹配到的內容均替換為s所表示的字符串;

技術分享圖片

split(s,a[,r]):以r為分隔符去切割字符串s,並將切割後的結果保存至a表示的數組中;

註意:awk的數組下標從1開始編號

~]# awk '{split($0,userinfo,":");print userinfo[1]}' /etc/passwd

技術分享圖片

substr(s,i[,n]):從s所表示的字符串中取子串,取法:從i表示的位置開始,取n個字符;

時間類函數:

systime():取當前系統時間,結果形式為時間戳;

9.2 用戶自定義函數

function f_name(p,q) {

...

}

技術分享圖片


文本處理三劍客之awk(原創)