天天看點

Linux學習筆記:awk詳細用法

一、基礎用法

awk:報告生成工具;把檔案中讀取到的每一行的每個字段分别進行格式化,然後進行顯示。

1

2

3

4

5

6

7

8

9

10

11

<code>[Linux85]</code><code>#awk -h</code>

<code>Usage: awk [POSIX </code><code>or</code> <code>GNU style options] </code><code>-</code><code>f progfile [</code><code>-</code><code>-</code><code>] </code><code>file</code> <code>...</code>

<code>Usage: awk [POSIX </code><code>or</code> <code>GNU style options] [</code><code>-</code><code>-</code><code>] </code><code>'program'</code> <code>file</code> <code>...</code>

<code>POSIX options:      GNU </code><code>long</code> <code>options:</code>

<code>    </code><code>-</code><code>f progfile     </code><code>-</code><code>-</code><code>file</code><code>=</code><code>progfile</code>

<code>    </code><code>-</code><code>F fs           </code><code>-</code><code>-</code><code>field</code><code>-</code><code>separator</code><code>=</code><code>fs    </code><code>#字段分隔符</code>

<code>    </code><code>-</code><code>v var</code><code>=</code><code>val      </code><code>-</code><code>-</code><code>assign</code><code>=</code><code>var</code><code>=</code><code>val</code>

<code>    </code><code>-</code><code>m[fr] val</code>

<code>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          </code> 

<code>awk [options] </code><code>'script'</code> <code>FILE</code> <code>...</code>

<code>awk [options] </code><code>'/pattern/{action}'</code> <code>FILE</code> <code>...</code>

四種分隔符:

輸入/輸出

行分隔符:$

字段分隔符:空白

模式

位址定界

/pattern1/,/pattern2/

/pattern/

可以 ! 取反

expression

表達式;&gt;, &gt;=, &lt;, &lt;=, ==, !=, ~

BEGIN{}

在周遊操作開始之前執行一次

END{}

在周遊操作結束之後、指令退出之前執行一次

<code>[Linux85]</code><code>#awk '/^soul/{print $0}' /etc/passwd /etc/shadow /etc/group</code>

<code>soul:x:</code><code>501</code><code>:</code><code>501</code><code>::</code><code>/</code><code>home</code><code>/</code><code>soul:</code><code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>soul:!!:</code><code>16166</code><code>:</code><code>0</code><code>:</code><code>99999</code><code>:</code><code>7</code><code>:::</code>

<code>soul:x:</code><code>501</code><code>:</code>

<code>[Linux85]</code><code>#</code>

<code>#ID号大于等于500的使用者</code>

<code>[Linux85]</code><code>#awk -F : '$3&gt;=500{print $1}' /etc/passwd</code>

<code>nfsnobody</code>

<code>gentoo</code>

<code>soul</code>

<code>BEGIN執行前操作</code>

<code>[Linux85]</code><code>#awk -F : 'BEGIN{print "UserName\n***********"}$3&gt;=500{print $1}' /etc/passwd</code>

<code>UserName</code>

<code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code><code>*</code>

awk的内置變量:

NF

字段數( The number of fields in the current input record.)

FS

field separator,讀取文本時,所使用字段分隔符

RS

Record separator,輸入文本資訊所使用的換行符;

OFS

輸出時使用字段分隔符,預設為空白(output field separator)

ORS

output record separator

<code>[Linux85]</code><code>#awk -F : '/^soul/{print $1,$7}' /etc/passwd</code>

<code>soul </code><code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             </code> 

<code>[Linux85]</code><code>#awk 'BEGIN{FS=":"}/^soul/{print $1,$7}' /etc/passwd</code>

<code>[Linux85]</code><code>#awk 'BEGIN{FS=":";OFS=":"}/^soul/{print $1,$7}' /etc/passwd</code>

<code>soul:</code><code>/</code><code>bin</code><code>/</code><code>bash</code>

12

13

14

15

<code>[Linux85]</code><code>#awk '!/^$|^#/{print $1}' /etc/sysctl.conf</code>

<code>net.ipv4.ip_forward</code>

<code>net.ipv4.conf.default.rp_filter</code>

<code>net.ipv4.conf.default.accept_source_route</code>

<code>kernel.sysrq</code>

<code>kernel.core_uses_pid</code>

<code>net.ipv4.tcp_syncookies</code>

<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>ip6tables</code>

<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>iptables</code>

<code>net.bridge.bridge</code><code>-</code><code>nf</code><code>-</code><code>call</code><code>-</code><code>arptables</code>

<code>kernel.msgmnb</code>

<code>kernel.msgmax</code>

<code>kernel.shmmax</code>

<code>kernel.shmall</code>

<code>[Linux85]</code><code>#ifconfig | awk '/inet addr/{print $2}' | awk -F : '!/127/{print $2}'</code>

<code>172.16</code><code>.</code><code>251.85</code>

二、awk的進階使用

1、print輸出:print item1, item2, ...

各項目之間使用逗号隔開,而輸出時則以空白字元分隔;

輸出的item可以為字元串或數值、目前記錄的字段(如$1)、變量或awk的表達式;數值會先轉換為字元串,而後再輸出;

print指令後面的item可以省略,此時其功能相當于print $0, 是以,如果想輸出空白行,則需要使用print "";

2、printf輸出:printf format, item1, item2, ...

其與print指令的最大不同是,printf需要指定format;

format用于指定後面的每個item的輸出格式;

printf語句不會自動列印換行符;\n

format格式的訓示符都以%開頭;後面跟一個字元;

%c

顯示字元的ASCII碼;

%d | %i

十進制整數;

%e | %E

科學計數法顯示數值;

%f

顯示浮點數;

%g | %G

以科學計數法的格式或浮點數的格式顯示數值;

%s

顯示字元串;

%u

無符号整數;

%%

顯示%自身;

<code>[Linux85]</code><code>#awk 'BEGIN{num1=20;num2=30; printf "%d %d\n",num1,num2}'</code>

<code>20</code> <code>30</code>

<code>#不顯示item;隻顯示的是格式;格式對應的後面的變量;是以需要一一對應</code>

修飾符

N

顯示寬度

-

左對齊

+

顯示數值符号;正負數

<code>[Linux85]</code><code>#awk -F: '{printf "%-14s %s\n",$1,$NF}' /etc/passwd</code>

<code>root           </code><code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>bin</code>            <code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>daemon         </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>adm            </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>lp             </code><code>/</code><code>sbin</code><code>/</code><code>nologin</code>

<code>sync           </code><code>/</code><code>bin</code><code>/</code><code>sync</code>

3、awk内置變量之資料變量

NR

The number of input records,awk指令所處理的記錄數;如果有多個檔案,這個數目會把處理的多個檔案中行統一計數;

Number of Field,目前記錄的field個數;

FNR

與NR不同的是,FNR用于記錄正處理的行是目前這一檔案中被總共處理的行數;

ARGV

數組,儲存指令行本身這個字元串,如awk '{print $0}' a.txt b.txt這個指令中,ARGV[0]儲存awk,ARGV[1]儲存a.txt;

ARGC

awk指令的參數的個數;

FILENAME

awk指令所處理的檔案的名稱;

ENVIROM

目前shell環境變量及其值的關聯數組;

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

<code>[Linux85]</code><code>#awk '{print NR,$0}' 1.txt</code>

<code>1</code> <code>one line</code>

<code>2</code> <code>two line</code>

<code>3</code> <code>three line</code>

<code>4</code> <code>four line</code>

<code>5</code> <code>five line</code>

<code>[Linux85]</code><code>#awk '{print NR,$0}' 2.txt</code>

<code>1</code> <code>six line</code>

<code>2</code> <code>seven line</code>

<code>3</code> <code>eight line</code>

<code>4</code> <code>nine line</code>

<code>5</code> <code>ten line</code>

<code>[Linux85]</code><code>#awk '{print NR,$0}' 1.txt 2.txt</code>

<code>6</code> <code>six line</code>

<code>7</code> <code>seven line</code>

<code>8</code> <code>eight line</code>

<code>9</code> <code>nine line</code>

<code>10</code> <code>ten line</code>

<code>#</code>

<code>[Linux85]</code><code>#awk '{print FNR,$0}' 1.txt 2.txt</code>

<code>[Linux85]</code><code>#awk -F: '/root/{print $1,"is a user in",ARGV[1]}' /etc/passwd</code>

<code>root </code><code>is</code> <code>a user </code><code>in</code> <code>/</code><code>etc</code><code>/</code><code>passwd</code>

<code>operator </code><code>is</code> <code>a user </code><code>in</code> <code>/</code><code>etc</code><code>/</code><code>passwd</code>

<code>[Linux85]#awk </code><code>'BEGIN{print ARGC}'</code> <code>/etc/passwd /etc/group /etc/shadow</code>

<code>4</code>

<code>[Linux85]#</code>

<code># </code><code>'BEGIN{print ARGC}'</code><code>本身也當成一個參數</code>

<code>[Linux85]</code><code>#awk '{print $0,"in",  FILENAME}' 1.txt 2.txt</code>

<code>one line </code><code>in</code> <code>1</code><code>.txt</code>

<code>two line </code><code>in</code> <code>1</code><code>.txt</code>

<code>three line </code><code>in</code> <code>1</code><code>.txt</code>

<code>four line </code><code>in</code> <code>1</code><code>.txt</code>

<code>five line  </code><code>in</code> <code>1</code><code>.txt</code>

<code>six line </code><code>in</code> <code>2</code><code>.txt</code>

<code>seven line </code><code>in</code> <code>2</code><code>.txt</code>

<code>eight line </code><code>in</code> <code>2</code><code>.txt</code>

<code>nine line </code><code>in</code> <code>2</code><code>.txt</code>

<code>ten line </code><code>in</code> <code>2</code><code>.txt</code>

4、輸出重定向

print items &gt; output-file

print items &gt;&gt; output-file

print items | command

特殊檔案描述符:

/dev/stdin:标準輸入

/dev/sdtout: 标準輸出

/dev/stderr: 錯誤輸出

/dev/fd/N: 某特定檔案描述符,如/dev/stdin就相當于/dev/fd/0;

5、awk的操作符

算術操作符

指派操作符

比較操作符

-x:負值

=:應[=]

x &lt; y   True if x is less than y.

+x:轉換為數值

+=

x &lt;= y  True if x is less than or equal to y.

x^y:次方

-=

x &gt; y   True if x is greater than y.

x**y:次方

*=

x &gt;= y  True if x is greater than or equal to y.

x*y

/=

x == y  True if x is equal to y.

x/y

%=

x != y  True if x is not equal to y.

x+y

^=

x ~ y   True if the string x matches the regexp denoted by y.

x-y

**=

x !~ y  True if the string x does not match the regexp denoted by y.

x%y

++

subscript in array  True if the array array has an element with the subscript subscript.

--

awk中;任何非0值或非空字元串都為真;反之為假。

條件表達式:

select?if-true-exp:if-false-exp

6、模式和常見的模式類型

模式:

awk 'program' input-file1 input-file2 ...

program:

pattern { action }

....

常見的模式:

Regexp

正規表達式,格式為/regular expression/

expresssion

表達式,其值非0或為非空字元時滿足條件,如:$1 ~ /foo/ 或 $1 == "soul",用運算符~(比對)和!~(不比對)。

Ranges

指定的比對範圍,格式為pat1,pat2

BEGIN/END

特殊模式,僅在awk指令執行前運作一次或結束前運作一次

Empty(空模式)

比對任意輸入行;

常見的Action

Expressions

Control statements

Compound statements

Input statements

Output statements

7、控制語句

if-else

   文法:if (condition) {then-body} else {[ else-body ]}

<code>[Linux85]</code><code>#awk -F : 'BEGIN{OFS=":"}{if ($3==0) {print $1,"Administrator";} else {print $1,"Common User"}}' /etc/passwd</code>

<code>root:Administrator</code>

<code>bin</code><code>:Common User</code>

<code>daemon:Common User</code>

<code>adm:Common User</code>

<code>lp:Common User</code>

<code>sync:Common User</code>

<code>shutdown:Common User</code>

<code>[Linux85]</code><code>#awk -F: '{if ($1=="root") printf "%-15s: %s\n",$1,"Admin";else printf "%-15s: %s\n",$1,"Common User"}' /etc/passwd</code>

<code>root           : Admin</code>

<code>bin</code>            <code>: Common User</code>

<code>daemon         : Common User</code>

<code>adm            : Common User</code>

<code>lp             : Common User</code>

<code>sync           : Common User</code>

<code>shutdown       : Common User</code>

<code>halt           : Common User</code>

<code>mail           : Common User</code>

<code>uucp           : Common User</code>

<code>operator       : Common User</code>

<code>games          : Common User</code>

<code>gopher         : Common User</code>

<code>ftp            : Common User</code>

<code>nobody         : Common User</code>

<code>dbus           : Common User</code>

<code>usbmuxd        : Common User</code>

<code>[Linux85]</code><code>#awk -F: -v sum=0 '{if ($3&gt;=500) sum++}END{print sum}' /etc/passwd</code>

<code>3</code>

<code>[Linux85]</code><code>#統計uid&gt;=500的使用者個數</code>

while

   文法:while (condition){statement1; statment2; ...}

<code>[Linux85]</code><code>#awk -F : '{i=1;while (i&lt;=3) {print $i;i++}}' /etc/passwd</code>

<code>root</code>

<code>x</code>

<code>0</code>

<code>bin</code>

<code>1</code>

<code>#列印出/etc/passwd前三個字段</code>

<code>[Linux85]</code><code>#awk -F: '{i=1;while (i&lt;=NF) { if (length($i)&gt;=4) {print $i}; i++ }}' /etc/passwd</code>

<code>/</code><code>root</code>

<code>/</code><code>bin</code><code>/</code><code>bash</code>

<code>/</code><code>bin</code>

<code>/</code><code>sbin</code><code>/</code><code>nologin</code>

do-while 至少執行一次循環體,不管條件滿足與否

   文法:do {statement1, statement2, ...} while (condition)

<code>[Linux85]</code><code>#awk -F: '{i=1;do {print $i;i++}while(i&lt;=3)}' /etc/passwd</code>

<code>daemon</code>

<code>2</code>

<code>[Linux85]</code><code>#awk -F: '{i=4;do {print $i;i--}while(i&gt;4)}' /etc/passwd</code>

<code>7</code>

<code>12</code>

for

   文法:for (variable assignment; condition; iteration process) {statement1, statement2, ...}

<code>[Linux85]</code><code>#awk -F: '{for(i=1;i&lt;=3;i++) if (i&lt;3){printf "%s:",$i} print $i}' /etc/passwd</code>

<code>root:x:</code><code>0</code>

<code>bin</code><code>:x:</code><code>1</code>

<code>daemon:x:</code><code>2</code>

<code>adm:x:</code><code>4</code>

<code>lp:x:</code><code>7</code>

<code>sync:x:</code><code>0</code>

<code>shutdown:x:</code><code>0</code>

for循環周遊數組元素

   文法: for (i in array) {statement1, statement2, ...}

<code>[Linux85]</code><code>#awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd</code>

<code> </code><code>/</code><code>sbin</code><code>/</code><code>shutdown:</code><code>1</code>

<code>       </code><code>/</code><code>bin</code><code>/</code><code>csh:</code><code>1</code>

<code>      </code><code>/</code><code>bin</code><code>/</code><code>bash:</code><code>2</code>

<code>  </code><code>/</code><code>sbin</code><code>/</code><code>nologin:</code><code>29</code>

<code>     </code><code>/</code><code>sbin</code><code>/</code><code>halt:</code><code>1</code>

<code>      </code><code>/</code><code>bin</code><code>/</code><code>sync:</code><code>1</code>

<code>#統計最後一個字段出現的次數</code>

case

文法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}

break 和 continue

next

提前結束對本行文本的處理,并接着處理下一行;

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

<code>bin</code> <code>1</code>

<code>adm </code><code>3</code>

<code>sync </code><code>5</code>

<code>halt </code><code>7</code>

<code>operator </code><code>11</code>

<code>gopher </code><code>13</code>

<code>nobody </code><code>99</code>

<code>dbus </code><code>81</code>

<code>usbmuxd </code><code>113</code>

<code>vcsa </code><code>69</code>

<code>rtkit </code><code>499</code>

<code>abrt </code><code>173</code>

<code>postfix </code><code>89</code>

<code>rpcuser </code><code>29</code>

<code>pulse </code><code>497</code>

<code>soul </code><code>501</code>

8、數組

array[index-expression]

index-expression可以使用任意字元串;需要注意的是,如果某資料組元素事先不存在,那麼在引用其時,awk會自動建立此元素并初始化為空串;是以,要判斷某資料組中是否存在某元素,需要使用index in array的方式。

要周遊數組中的每一個元素,需要使用如下的特殊結構:

   for (var in array) { statement1, ... }

   其中,var用于引用數組下标,而不是元素值;

删除數組中的變量:delete  array[index]

<code>[Linux85]</code><code>#netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'</code>

<code>ESTABLISHED </code><code>2</code>

<code>LISTEN </code><code>10</code>

9、awk的内置函數

split(string, array [, fieldsep [, seps ] ])

将string表示的字元串以fieldsep為分隔符進行分隔,并将分隔後的結果儲存至array為名的數組中;數組下标為從1開始的序列;

<code>[Linux85]</code><code>#df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]&gt;=10){print $1}}'</code>

<code>/</code><code>dev</code><code>/</code><code>sda1</code>

<code>/</code><code>dev</code><code>/</code><code>mapper</code><code>/</code><code>vg0</code><code>-</code><code>usr</code>

<code>#磁盤使用率大于等于%10的顯示出來</code>

length([string]):傳回string字元串中字元的個數;

<code>[Linux85]</code><code>#awk -F: '{for(i=1;i&lt;=NF;i++) { if (length($i)&gt;=4) {print $i}}}' /etc/passwd</code>

<code>/</code><code>sbin</code>

substr(string, start [, length ])

取string字元串中的子串,從start開始,取length個;start從1開始計數;

system(command):執行系統command并将結果傳回至awk指令

systime():取系統目前時間

tolower(s):将s中的所有字母轉為小寫

toupper(s):将s中的所有字母轉為大寫

10、使用者自定義函數

自定義函數使用function關鍵字。格式如下:

function F_NAME([variable])

{

statements

}

example:

<code>#統計目前系統上每個用戶端IP的連接配接中狀處于ESTABLISHED的連接配接态的個數;</code>

<code>[Linux85]</code><code>#netstat -tn | awk '/ESTABLISHED\&gt;/{split($5,ip,":");num[ip[1]]++}END{for (i in num) printf "%s %d\n", i, num[i]}'</code>

<code>172.16</code><code>.</code><code>254.28</code> <code>2</code>

<code>#統計ps aux指令執行時,目前系統上各狀态的程序的個數;</code>

<code>[Linux85]</code><code>#ps aux | awk '!/^USER/{state[$8]++}END{for (i in state) printf "%s %d\n",i,state[i]}'</code>

<code>S&lt; </code><code>2</code>

<code>S&lt;sl </code><code>1</code>

<code>Ss </code><code>18</code>

<code>SN </code><code>1</code>

<code>S </code><code>69</code>

<code>Ss</code><code>+</code> <code>6</code>

<code>Ssl </code><code>2</code>

<code>R</code><code>+</code> <code>1</code>

<code>S</code><code>+</code> <code>2</code>

<code>Sl </code><code>2</code>

<code>S&lt;s </code><code>1</code>

<code>#統計ps aux指令執行時,目前系統上各使用者的程序的個數;</code>

<code>[Linux85]</code><code>#ps aux | awk '!/^USER/{state[$1]++}END{for (i in state) printf "%s %d\n",i,state[i]}'</code>

<code>rpc </code><code>1</code>

<code>dbus </code><code>1</code>

<code>68</code> <code>2</code>

<code>postfix </code><code>2</code>

<code>rpcuser </code><code>1</code>

<code>root </code><code>96</code>

<code>gentoo </code><code>2</code>

<code>#顯示ps aux指令執行時,目前系統上其VSZ(虛拟記憶體集)大于10000的程序及其PID;</code>

<code>[Linux85]</code><code>#ps aux | awk '!/USER/{if($5&gt;10000) print $2,$11}'</code>

<code>1</code> <code>/</code><code>sbin</code><code>/</code><code>init</code>

<code>397</code> <code>/</code><code>sbin</code><code>/</code><code>udevd</code>

<code>1184</code> <code>auditd</code>

<code>1209</code> <code>/</code><code>sbin</code><code>/</code><code>rsyslogd</code>

<code>1251</code> <code>rpcbind</code>

<code>1282</code> <code>dbus</code><code>-</code><code>daemon</code>

<code>1292</code> <code>NetworkManager</code>

<code>1297</code> <code>/</code><code>usr</code><code>/</code><code>sbin</code><code>/</code><code>modem</code><code>-</code><code>manager</code>

<code>1311</code> <code>rpc.statd</code>

<code>1344</code> <code>cupsd</code>

<code>1354</code> <code>/</code><code>usr</code><code>/</code><code>sbin</code><code>/</code><code>wpa_supplicant</code>

<code>1392</code> <code>hald</code>

<code></code>

本文轉自Mr_陳 51CTO部落格,原文連結:http://blog.51cto.com/chenpipi/1391178,如需轉載請自行聯系原作者