awk使用詳解

一、awk介紹:

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

awk模式

1.BEGIN模式:讓用戶指定在第一條輸入記錄被處理之前所發生的動作,通常可在這裏設置全局變量

2.END模式:讓用戶在最後一條輸入記錄被讀取之後發生的動作

3.正則表達式:使用通配符的擴展集

4.關係表達式:可以用關係運算符進行操作,可以是字符


awk的輸出print和printf

print的使用格式:print  item1,item2,…

使用格式介紹:

1.各項目之間使用逗號隔開,而輸出時則以空白字符分隔

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

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

[root@localhost ~]# awk 'BEGIN { print "line one\nline two\nline three"}'
line one
line two
line three
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4

printf的格式使用:prinf  format,item1,item2,…


格式說明:

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

2、format用於指定後面的每個item的輸出格式;

3、printf語句不會自動打印換行符;\n

format格式的指示符都以%開頭,後跟一個字符;如下:

%c: 顯示字符的ASCII碼;

%d, %i:十進制整數;

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

%f: 顯示浮點數;

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

%s: 顯示字符串;

%u: 無符號整數;

%%: 顯示%自身;


修飾符:

N: 顯示寬度;

-: 左對齊;

+:顯示數值符號;

[root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd
root            0
bin             1
daemon         2aw

二、awk的變量類型

用戶自定義變量

gawk允許用戶自定義自己的變量以便在程序代碼中使用,變量名命名規則與大多數編程語言相同,只能使用字母、數字和下劃線,且不能以數字開頭。gawk變量名稱區分字符大小寫。

在腳本中賦值變量

在gawk中給變量賦值使用賦值語句進行,例如:

awk'BEGIN{var="variable testing";print var}'

在命令行中使用賦值變量

gawk命令也可以在“腳本”外爲變量賦值,並在腳本中進行引用。例如,上述的例子還可以改寫爲:

awk -vvar="variable testing" 'BEGIN{print var}'

內置變量表

屬性

說明

$0

當前記錄(作爲單個變量)

$1~$n

當前記錄的第n個字段,字段間由FS分隔

FS

輸入字段分隔符 默認是空格

NF

當前記錄中的字段個數,就是有多少列

NR

已經讀出的記錄數,就是行號,從1開始

RS

輸入的記錄分隔符默 認爲換行符

OFS

輸出字段分隔符 默認也是空格

ORS

輸出的記錄分隔符,默認爲換行符

ARGC

命令行參數個數

ARGV

命令行參數數組

FILENAME

當前輸入文件的名字

IGNORECASE

如果爲真,則進行忽略大小寫的匹配

ARGIND

當前被處理文件的ARGV標誌符

CONVFMT

數字轉換格式 %.6g

ENVIRON

UNIX環境變量

ERRNO

UNIX系統錯誤消息

FIELDWIDTHS

輸入字段寬度的空白分隔字符串

FNR

當前記錄數

OFMT

數字的輸出格式 %.6g

RSTART

被匹配函數匹配的字符串首

RLENGTH

被匹配函數匹配的字符串長度

SUBSEP

\034

輸出重定向

print items > output-file

print items >> output-file

print items | command


特殊文件描述符:

/dev/stdin:標準輸入

/dev/sdtout: 標準輸出

/dev/stderr: 錯誤輸出

/dev/fd/N: 某特定文件描述符,如/dev/stdin就相當於/dev/fd/0;


例子:

# awk -F: '{printf "%-15s %i\n",$1,$3 > "/dev/stderr" }' /etc/passwd


三、awk的操作符

算術操作符:

-x: 負值

+x: 轉換爲數值;

x^y: x的y次冪

x**y: 次方

x*y: 乘法

x/y:除法

x+y:加法

x-y:減法

x%y:取餘


賦值操作符:

=

+=

-=

*=

/=

%=

^=

**=

++

--

需要注意的是,如果某模式爲=號,此時使用/=/可能會有語法錯誤,應以/[=]/替代;

布爾值

awk中,任何非0值或非空字符串都爲真,反之就爲假;

比較操作符

x < y     True if x is less than y.

x <= y   True if x is less than or equal to y.

x > y      True if x is greater than y.

x >= y    True if x is greater than or equal to y.

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

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

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

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

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

表達式間的邏輯關係符

&&

||

條件表達式:

selector?if-true-exp:if-false-exp


if selector; then

 if-true-exp

else

 if-false-exp

fi


a=3

b=4

a>b?a is max:b ia max

函數調用:

function_name (para1,para2)

四、awk的控制語句:

if-else

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

# awk '{if ($3==0) {print $1, "Adminitrator";} else { print $1,"Common User"}}' /etc/passwd

例子:

awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd

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

awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd


while

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

awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd

awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd

awk '{i=1;while (i<=NF) {if ($i>=100) print $i; i++}}' hello.txt


hello.txt文件的內容爲一堆隨機數。


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

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

awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd

awk -F: '{i=4;do {print $i;i--}while(i>4)}' /etc/passwd


for

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

awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd

awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd


for循環還可以用來遍歷數組元素

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

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


BASH[/bin/bash]++

BASH[/sbin/nologin]


BASH[/bin/bash]=1

BASH[/sbin/nologin]=2

BASH[/bin/sync]=1


/bin/bash: 1

/sbin/nologin: 2

/bin/sync: 1


case

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


break 和 continue

常用於循環或case語句中


next

提前結束對本行文本的處理,並接着處理下一行;例如,下面的命令將顯示其ID號爲奇數的用戶:

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


五、awk中使用數組


數組


array[index-expression]


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


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

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

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


例子:

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

每出現一被/^tcp/模式匹配到的行,數組S[$NF]就加1,NF爲當前匹配到的行的最後一個字段,此處用其值做爲數組S的元素索引;


awk '{counts[$1]++}; END {for(url in counts) print counts[url], url}' /var/log/httpd/access_log

用法與上一個例子相同,用於統計某日誌文件中IP地的訪問量


刪除數組變量


從關係數組中刪除數組索引需要使用delete命令。使用格式爲:


delete  array[index]


六、awk的內置函數


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

功能:將string表示的字符串以fieldsep爲分隔符進行分隔,並將分隔後的結果保存至array爲名的數組中;數組下標爲從1開始的序列;


# netstat -ant | awk '/:80\>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50


# netstat -tan | awk '/:80\>/{split($5,clients,":");ip[clients[4]]++}END{for(a in ip) print ip[a],a}' | sort -rn | head -50


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


length([string])

功能:返回string字符串中字符的個數;



substr(string, start [, length])

功能:取string字符串中的子串,從start開始,取length個;start從1開始計數;


system(command)

功能:執行系統command並將結果返回至awk命令


systime()

功能:取系統當前時間


tolower(s)

功能:將s中的所有字母轉爲小寫


toupper(s)

功能:將s中的所有字母轉爲大寫


用戶自定義函數


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


function F_NAME([variable])

{

statements

}


函數還可以使用return語句返回值,格式爲“return value”。



Linux Web服務器網站故障分析常用的命令

系統連接狀態篇:

1.查看TCP連接狀態

netstat -nat |awk ‘{print $6}’|sort|uniq -c|sort -rn


netstat -n | awk ‘/^tcp/ {++S[$NF]};END {for(a in S) print a, S[a]}’ 或

netstat -n | awk ‘/^tcp/ {++state[$NF]}; END {for(key in state) print key,"\t",state[key]}’

netstat -n | awk ‘/^tcp/ {++arr[$NF]};END {for(k in arr) print k,"t",arr[k]}’


netstat -n |awk ‘/^tcp/ {print $NF}’|sort|uniq -c|sort -rn


netstat -ant | awk ‘{print $NF}’ | grep -v ‘[a-z]‘ | sort | uniq -c




2.查找請求數請20個IP(常用於查找攻來源):


netstat -anlp|grep 80|grep tcp|awk ‘{print $5}’|awk -F: ‘{print $1}’|sort|uniq -c|sort -nr|head -n20


netstat -ant |awk ‘/:80/{split($5,ip,":");++A[ip[1]]}END{for(i in A) print A[i],i}’ |sort -rn|head -n20


3.用tcpdump嗅探80端口的訪問看看誰最高


tcpdump -i eth0 -tnn dst port 80 -c 1000 | awk -F"." ‘{print $1"."$2"."$3"."$4}’ | sort | uniq -c | sort -nr |head -20


4.查找較多time_wait連接


netstat -n|grep TIME_WAIT|awk ‘{print $5}’|sort|uniq -c|sort -rn|head -n20


5.找查較多的SYN連接


netstat -an | grep SYN | awk ‘{print $5}’ | awk -F: ‘{print $1}’ | sort | uniq -c | sort -nr | more


6.根據端口列進程


netstat -ntlp | grep 80 | awk ‘{print $7}’ | cut -d/ -f1




網站日誌分析篇1(Apache):


1.獲得訪問前10位的ip地址


cat access.log|awk ‘{print $1}’|sort|uniq -c|sort -nr|head -10

cat access.log|awk ‘{counts[$(11)]+=1}; END {for(url in counts) print counts[url], url}’


2.訪問次數最多的文件或頁面,取前20


cat access.log|awk ‘{print $11}’|sort|uniq -c|sort -nr|head -20


3.列出傳輸最大的幾個exe文件(分析下載站的時候常用)


cat access.log |awk ‘($7~/.exe/){print $10 " " $1 " " $4 " " $7}’|sort -nr|head -20


4.列出輸出大於200000byte(約200kb)的exe文件以及對應文件發生次數


cat access.log |awk ‘($10 > 200000 && $7~/.exe/){print $7}’|sort -n|uniq -c|sort -nr|head -100


5.如果日誌最後一列記錄的是頁面文件傳輸時間,則有列出到客戶端最耗時的頁面


cat access.log |awk ‘($7~/.php/){print $NF " " $1 " " $4 " " $7}’|sort -nr|head -100


6.列出最最耗時的頁面(超過60秒的)的以及對應頁面發生次數


cat access.log |awk ‘($NF > 60 && $7~/.php/){print $7}’|sort -n|uniq -c|sort -nr|head -100


7.列出傳輸時間超過 30 秒的文件


cat access.log |awk ‘($NF > 30){print $7}’|sort -n|uniq -c|sort -nr|head -20


8.統計網站流量(G)


cat access.log |awk ‘{sum+=$10} END {print sum/1024/1024/1024}’


9.統計404的連接


awk ‘($9 ~/404/)’ access.log | awk ‘{print $9,$7}’ | sort


10. 統計http status


cat access.log |awk ‘{counts[$(9)]+=1}; END {for(code in counts) print code, counts[code]}'

cat access.log |awk '{print $9}'|sort|uniq -c|sort -rn


10.蜘蛛分析,查看是哪些蜘蛛在抓取內容。


/usr/sbin/tcpdump -i eth0 -l -s 0 -w - dst port 80 | strings | grep -i user-agent | grep -i -E 'bot|crawler|slurp|spider'


網站日分析2(Squid篇)按域統計流量


zcat squid_access.log.tar.gz| awk '{print $10,$7}' |awk 'BEGIN{FS="[ /]"}{trfc[$4]+=$1}END{for(domain in trfc){printf "%st%dn",domain,trfc[domain]}}'


數據庫篇

1.查看數據庫執行的sql


/usr/sbin/tcpdump -i eth0 -s 0 -l -w - dst port 3306 | strings | egrep -i 'SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL'


系統Debug分析篇

1.調試命令

strace -p pid

2.跟蹤指定進程的PID

gdb -p pid






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章