一、AWK簡介:
AWK是一個文本報告生成器,它不僅是Linux中也是任何環境中現有的功能最強大的數據處理引擎之一,它具有編程及數據操作語言,提供了極其強大的功能:可以進行樣式裝入、流控制、數學運算符、過程控制語句甚至於內置的變量和函數。它具備了一個完整的語言所應具有的幾乎所有精美特性。它允許使用者創建簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表等等功能。
在最初創造AWK時,其目的是用於文本處理,並且這種語言的基礎是,只要在輸入數據中有模式匹配,就執行一系列指令。AWK會掃描文件中的每一行,查找與命令行中所給定內容相匹配的內容,如果發現匹配內容,則進行下一個編程步驟。如果找不到匹配內容,則繼續處理下一行。
二、AWK語法:
awk [option]...'/PATTERN/{action}' FILE;語法中'/PATTERN/{action}'部分又被稱爲awk的腳本。
三、AWK基本應用示例:
1、打印文本文件的某個字段,默認分隔符爲空格:
[root@client2 html]# awk '{print $1}' /etc/fstab # # # # # # # /dev/mapper/vg0-root UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3 /dev/mapper/vg0-usr /dev/mapper/vg0-var /dev/mapper/vg0-swap tmpfs devpts sysfs proc
2、打印文本文件的多個字段:
[root@client2 html]# awk '{print $1,$2}' /etc/fstab # # /etc/fstab # Created # # Accessible # See # /dev/mapper/vg0-root / UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3 /boot /dev/mapper/vg0-usr /usr /dev/mapper/vg0-var /var /dev/mapper/vg0-swap swap tmpfs /dev/shm devpts /dev/pts sysfs /sys proc /proc
3、打印所有字段,$0用於引用所有字段:
[root@client2 html]# awk '{print $0}' /etc/fstab # # /etc/fstab # Created by anaconda on Mon Jul 28 19:06:01 2014 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/vg0-root / ext4 defaults 1 1 UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3 /boot ext4 defaults 1 2 /dev/mapper/vg0-usr /usr ext4 defaults 1 2 /dev/mapper/vg0-var /var ext4 defaults 1 2 /dev/mapper/vg0-swap swap swap defaults 0 0 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0
4、顯示指定的某行的某字段信息或打印連續的若干行:
[root@client1 ~]# awk 'NR==10{print $1}' /etc/fstab UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3 [root@node1 pam.d]# awk 'NR==8,NR==12' /etc/fstab # /dev/mapper/vg0-root / ext4 defaults 1 1 UUID=fbb4629b-1279-4a2a-9f49-18faa0e5bece /boot ext4 defaults 1 2 /dev/mapper/vg0-usr /usr ext4 defaults 1 2 /dev/mapper/vg0-var /var ext4 defaults 1 2
5、NF(Number of Field) 打印每行有幾個字段,變量NF用於表示一行內的字段數,在AWK中引用變量時不需要加$,但是如果變量前加了$,如NF,那麼就是引用對應的字段的:
[root@client2 html]# awk '{print NF}' /etc/fstab 0 1 2 10 1 9 12 1 6 6 6 6 6 6 6 6 6
6、每行中最後一個字段的調用方式爲$NF:
[root@client2 html]# awk '{print $NF}' /etc/fstab # /etc/fstab 2014 # '/dev/disk' info # 1 2 2 2 0 0 0 0 0
7、FS:Field Seperator,輸入分隔符,默認是空格:
8、OFS:輸出時的字段分隔符
9、語法表達式的/PATTERN/可以使用比較表達式,表達式用>,>=,<,<=,!=,==,~等比較字符來連接,比較的字符串與比較字符不需要用空格隔開,表達式也是正確的:
[root@client2 html]# awk -F: '$3 >= 500{print $1}' /etc/passwd nfsnobody
[root@client2 html]# awk -F: '$3 < 500{print$1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail uucp operator games gopher ftp nobody dbus usbmuxd vcsa rtkit rpc avahi-autoipd abrt haldaemon gdm ntp apache saslauth postfix rpcuser pulse sshd tcpdump
[root@client2 html]# awk -F: '$3 == 0{print $1}' /etc/passwd root
10、模式匹配示例:AWK的模式與action字段之間不需要空格分開,比較表達式兩端與比較表達式字符之間不需要空格,而action與要處理的字段之間也不需要空格,整個表達式都連在一起也是正確的,只是屬於模式匹配的部分用//括起來,屬於action字段的要用{}括起來:
[root@client2 html]# awk -F: '$7~/bash$/{print$1}' /etc/passwd root
11、顯示不相鄰的多個字段,$1$7連在一起,$1 $7用空格分隔,$1,$7用逗號分隔,注意看顯示的效果:
[root@client2 ~]# awk -F: '$7~/bash$/{print$1$7}' /etc/passwd root/bin/bash [root@client2 ~]# awk -F: '$7~/bash$/{print$1 $7}' /etc/passwd root/bin/bash [root@client2 ~]# awk -F: '$7~/bash$/{print$1,$7}' /etc/passwd root /bin/bash
12、AWK中的action字段可以有多個,多個action字段要用{}括起來,比如,在輸出的字段前輸出表頭:
[root@client1 ~]# awk -F: 'BEGIN{print"username shell"}$7~/bash$/{print$1,$7}' /etc/passwd username shell root /bin/bash
下面這條語句是自己測試的語句,寫法是錯誤的,計算機在識別用戶輸入的命令時所做的語法分析是命令選項參數,參數中又有相對應的格式要求,比如模式和action,而下面語句中的action放在了前面,那麼計算機在識別整個字符串的時候就會認爲是一個命令加了一個要處理的參數,而我們要表達的模式匹配用來匹配某些行的效果就出不來了,這個字段要寫在action的前面,而不能在後面出現,它被計算機識別爲了其他的不能識別的字符。而如果要在action中使用多個命令,可以使用;來分隔多個action,模式也是一樣,也是用;來分隔開,但是總體上來說,模式和action要有前有後,不能混亂,如果在做模式匹配前,先對行進行一些處理操作,需要使用BEGIN模式,如果要在行處理之後做一些操作就要使用END模式,BEGIN模式是打破了常規的語法順序的,但是在程序的內部機制上被識別和匹配,而不是語法錯誤。
[root@client1 ~]# awk -F: '{print"username shell"}$7~/bash$/{print$1,$7}' /etc/passwd
13、顯示以bash結尾的且該行的第三字段數值小於500的行的第1和第3字段:
[root@client1 ~]# awk -F: '$7~/bash$/&&$3<500{print$1,$3}' /etc/passwd root 0
14、顯示以bash結尾且該行第三個字段數值大於500的行的第1,第3,第7字段:
[root@client1 ~]# awk -F: '$7~/bash$/&&$3>500{print$1,$3,$7}' /etc/passwd
15、顯示第三字段數值小於500的行的第1,第3,第7字段,結果中可以看到只有root用戶是以bash結尾,所以之前的awk語句的寫法是正確的:
[root@client1 ~]# awk -F: '$3<500{print$1,$3,$7}' /etc/passwd root 0 /bin/bash bin 1 /sbin/nologin daemon 2 /sbin/nologin adm 3 /sbin/nologin lp 4 /sbin/nologin sync 5 /bin/sync shutdown 6 /sbin/shutdown halt 7 /sbin/halt mail 8 /sbin/nologin uucp 10 /sbin/nologin operator 11 /sbin/nologin games 12 /sbin/nologin gopher 13 /sbin/nologin ftp 14 /sbin/nologin nobody 99 /sbin/nologin dbus 81 /sbin/nologin usbmuxd 113 /sbin/nologin vcsa 69 /sbin/nologin rtkit 499 /sbin/nologin rpc 32 /sbin/nologin avahi-autoipd 170 /sbin/nologin abrt 173 /sbin/nologin haldaemon 68 /sbin/nologin gdm 42 /sbin/nologin ntp 38 /sbin/nologin apache 48 /sbin/nologin saslauth 498 /sbin/nologin postfix 89 /sbin/nologin rpcuser 29 /sbin/nologin pulse 497 /sbin/nologin sshd 74 /sbin/nologin tcpdump 72 /sbin/nologin
16、BEGIN模式示例,只有BEGIN模式字符開頭,後面從能用{}括起來action,後面從有可能再從頭查找PATTERN字串:
[root@client1 ~]# awk -F: 'BEGIN{print"username,shell"}$7~/bash$/{print$1,$7}' /etc/passwd username,shell root /bin/bash
要注意多個要顯示的字段或者字符串之間如果要用逗號分隔,那麼表示他們是不同的字段,如果未指定就要用默認的分隔符分隔開顯示,如果這些字段之間沒有用逗號分隔,那麼默認他們就被連起來顯示,在AWK中要表示多個連續的字段,沒有類似於其他表達方式的-等等連接符,只能是用其他的方式去遍歷需要顯示的多個字段。
[root@client1 ~]# awk -F: 'BEGIN{print"username,shell"}$7~/bash$/{print$1,$7}END{print"=====end====="}' /etc/passwd username,shell root /bin/bash =====end=====
17、BEGIN模式:在{action}開始之前執行一次,製作表頭;
END模式:在{action}結束之後執行一次,製作表尾;
要從程序的運作機制角度去考慮語句的寫法會很容易記憶,寫語句時也不容易出錯。
而通常情況下BEGIN模式是用來指定輸入分隔符和輸出分隔符的,用法如下:
[root@client1 ~]# awk 'BEGIN{FS=":"}$7~/bash$/{print$1,$7}' /etc/passwd root /bin/bash [root@client1 ~]# awk 'BEGIN{FS=":";OFS=":"}$7~/bash$/{print$1,$7}' /etc/passwd root:/bin/bash
注意:BEGIN模式和END模式後面的模式字段要用{}括起來,裏面的分隔符要用“”引起來表示其爲前面變量的值,沒有該“”是語法錯誤,在awk中大寫的字符都是有特殊意義的,所以爲這個變量賦值的方式就決定了要這樣去用,否則就是錯誤,同樣,多個變量之間的賦值操作要用;隔開,否則也是語法錯誤,都要注意!