首頁 > 軟體

Linux高階文字處理之gawk語法和基礎命令

2020-06-16 17:22:04

一、引言

Awk 是一個維護和處理文字資料檔案的強大語言。在文字資料有一定的格式,即每行封包 含多個以分界符分隔的欄位時,顯得尤其有用。 即便是輸入檔案沒有一定的格式,你仍然可 以使用 awk 進行基本的處理。 Awk 當然也可以沒有輸入檔案,那不是必須的。 簡言之, AWK 是一種能處理從瑣碎的小事到日常例行公事的強大語言。

二、awk語法

1.基礎語法:

awk [-F  field-separator] '/pattern/ {action}' input-file
(或者)
awk [-F  field-separator] '{action}' input-file

上面語法中:

  • -F 為欄位分界符。如果不指定,預設會使用空格作為分界符。

  • /pattern/和{action}需要用單引號引起來。

  • /pattern/是可選的。如果不指定, awk 將處理輸入檔案中的所有記錄。如果指定一個模式, awk 則只處理匹配指定的模式的記錄。

  • {action} 為 awk 命令,可以是單個命令,也可以多個命令。整個 action(包括裡面的所有命令)都必須放在{ 和 }之間。

  • Input-file 即為要處理的檔案

範例1:列印/etc/passwd檔案中mail使用者所在行的使用者名稱mail

[root@localhost ~]# grep '^mail' /etc/passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@localhost ~]# awk -F: '/mail/{print $1}' /etc/passwd #-F ":"也是正確的
mail

2.awk指令碼:

當需要執行很多 awk 命令時, 可以把/pattern/{action}這一部分放到單獨的檔案中,然後調 用它:

awk –Fs –f myscript.awk input-file  #[-F  field-separator]簡寫 -FS

也可以在這個檔案中設定欄位分界符(後面詳述),然後呼叫:

awk –f myscript.awk input-file

二、Awk 程式結構(BEGIN,body,END)區域

1.BEGIN 區域

Begin 區域的語法:

BEGIN { awk-commands }

說明:BEGIN 區域的命令只最開始、在 awk 執行 body 區域命令之前執行一次。

  • BEGIN 區域很適合用來列印報文頭部資訊,以及用來初始化變數。

  • BEGIN 區域可以有一個或多個 awk 命令

  • 關鍵字 BEGIN 必須要用大寫

  • BEGIN 區域是可選的

2.body 區域

body 區域的語法:

/pattern/ {action}
  • body 區域的命令每次從輸入檔案讀取一行就會執行一次

  • 如果輸入檔案有 10 行,那 body 區域的命令就會執行 10 次(每行執行一次)

  • Body 區域沒有用任何關鍵字表示,只有用正則模式和命令。

3.END block

END 區域的語法:

  • END { awk-commands }

  • END 區域在 awk 執行完所有操作後執行,並且只執行一次。

  • END 區域很適合列印報文結尾資訊,以及做一些清理動作

  • END 區域可以有一個或多個 awk 命令

  • 關鍵字 END 必須要用大寫

  • END 區域是可選的

awk執行流程圖:

範例1:

[root@localhost ~]# awk '
> BEGIN{FS=":";print "----header----"}   #列印內容字串要用雙引號,單引號有語法錯誤
> /mail/{print $1}
> END{print "----footer----"}
> ' /etc/passwd

----header----
mail
----footer----

提示:如果命令很長,即可以放到單行執行,也可以用折成多行執行。

範例2:通過awk指令碼執行範例1中的命令

[root@localhost ~]# cat myscript.awk 
BEGIN{
FS=":"
print "----header----"
}

/mail/{
print $1
}

END{
print "----footer----"
}
[root@localhost ~]# awk -f myscript.awk /etc/passwd
----header----
mail
----footer----

說明:awk 指令碼中,注釋以#開頭。

只使用 BEGIN 區域在 awk 中是符合語法的。在沒有使用 body 區域時,不需要指定輸入檔案, 因為 body 區域只在輸入檔案上執行。 所以在執行和輸入檔案無關的工作時,可以只使用 BEGIN 區域。

範例3:只使用BEGIN無輸入檔案

[root@localhost ~]# awk 'BEGIN{print "HELLO WORLD"}'
HELLO WORLD

4.多個輸入檔案:

awk 指定多個輸入檔案。如果指定了兩個檔案,那麼 body 區域會首先在第一 個檔案的所有行上執行,然後在第二個檔案的所有行上執行。

範例4:多檔案處理

[root@localhost ~]# awk -F: '
> BEGIN{print "----header----"}
> /mail/{print $1}
> END{print "----footer----"}
> ' /etc/passwd /etc/group
----header----
mail
mail
----footer----

注意:即是指定了多個檔案, BEGIN 和 END 區域,仍然只會執行一次。

三、列印命令

預設情況下,awk 的列印命令 print(不帶任何引數)會列印整行資料。下面的例子等價於”cat employee.txt”命令。

範例1:不帶引數

[root@localhost ~]# awk '{print}' emp
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager

範例2:也可以通過傳遞變數”$欄位序號”作為 print 的引數來指定要列印的欄位。

[root@localhost ~]# awk '{print $2}' ./emp  #預設以空格為分隔符
Doe,CEO
Smith,IT
Reddy,Sysadmin
Ram,Developer
Miller,Sales

範例3:輸出雇員姓名與職位

[root@localhost ~]# cat emp
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager

[root@localhost ~]# awk '
>BEGIN{FS=",";print "-------nNAME  Titlen--------n"}
>{print $2,"t",$3}  #列印多變數,之間用逗號或者空格分隔
>END{print "----------------"}' emp
-------
NAME  Title
--------

John Doe         CEO
Jason Smith      IT Manager
Raj Reddy        Sysadmin
Anand Ram        Developer
Jane Miller      Sales Manager
----------------

說明:請注意, $0 代表整條記錄。 下面兩個命令是等價的,都列印 employee.txt 的所有行:

awk '{print}' emp
awk '{print $0}' emp

四、模式匹配

只在匹配特殊模式的行數執行 awk 命令。

範例1:只處理匹配行

[root@localhost ~]# awk -F, '/Manager/{print $2,$3}' emp
Jason Smith IT Manager
Jane Miller Sales Manager

範例2:只列印僱員 id 為 102 的雇員的資訊

[root@localhost ~]# awk -F, '/^102/{print "Emp is 102 is",$2}' emp 
Emp is 102 is Jason Smith

本文永久更新連結地址http://www.linuxidc.com/Linux/2017-02/140316.htm


IT145.com E-mail:sddin#qq.com