Linux-awk命令詳解

awk 命令詳解

  awk 是一種編程語言,用於在linux/nuix下對文本和數據進行處理。數據能夠來自標準輸入、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能,是linux/unix下的一個強大的編程工具。它在命令行中使用,但更可能是做爲腳原本使用。linux

  awk 的處理文本和數據的方式是這樣的,它逐行掃描文件,從第一行到最後一行,尋找匹配的特定模式的行,並在這些行上進行你想要的操做。若是沒有指定處理動做,則把匹配的行顯示到標準輸出(屏幕),若是沒有指定模式,則全部被操做所指定的行都被處理。awk分別表明其做者姓氏的第一個字母。由於它的做者是三個恩,分別是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell實驗室和GNU的一些擴展。正則表達式

awk命令兩種使用方式:shell

  (1)命令行模式:awk [options] 'commands' file(s)編程

  (2)腳本模式:awk [options] -f scriptfile file[s]數組

awk 命令模式

awk [options] 'commands' file(s) 

option:
    -F 定義字段分割符號
    -v 定義變量並賦值
command:
    1、範圍說明或者正則表達式或者{awk命令語句1;awk命令語句2;}
    2、範圍說明部分能夠是BEGIN、END、邏輯表達式或者爲空
    3、awk命令語句間用分號間隔
    4、引用shell變量時須要用雙引號引發,命令模式都在單引號''裏面
    
    BEGIN{}    {}        END{}
    行處理前     行處理    行處理後

命令格式:
awk 'pattern' filename               示例:awk '/root/' /etc/passwd
awk '{action}' filename              示例:awk -F: '{print $1}' /etc/passwd
awk 'pattern {action}' filename      示例:awk -F: '/root/{print $1,$3}'    /etc/passwd          
示例:awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd command |awk 'pattern {action}' 示例:df -P | grep '/' |awk '$4 > 25000 {print $4}'

字段分割及相關變量緩存

$1,$2,$3...$n:awk中用該順序形式表示files中每行以間隔符號分割的各列的不一樣字段
$0             表示文本自己
NF             表示當前記錄的字段數(列數)
$NF            最後一列
$(NF-1)        倒數第二列
FNR/NR         行號
FILENAME       文件名
"\t"           製表符
RS             換行符
""             打印字符串
FS             定義間隔符
~              匹配,與==相比不是精確比較
!~             不匹配,不精確比較
==             等於,必須所有相等,精確比較
/[0-9][0-9]+/  兩個或兩個以上數字
-F'[:#/]'      定義三個分隔符
# awk -F: '{print $0}' /etc/passwd        //打印文件全部內容
# awk -F: '{print NR, $0}' /etc/passwd /etc/hosts    //打印文件全部內容,幷包括行號
# awk -F: '{print FNR,$0}' /etc/passwd /etc/hosts
# awk -F: '{print $0,NF}' /etc/passwd    //保留記錄的字段數
# awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd    //輸入字段分隔符,默認爲空格

格式化輸出:bash

print函數
# date |awk '{print "Month: "$2 "\nYear: "$NF}'
# awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd
# awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd
# head -5 /etc/passwd|awk -F: 'BEGIN {print "user\thomedir\tshell"RS"***********************"};{print $1"\t"$(NF-1)"\t"$NF};END {print"************END************"}
print函數
# date |awk '{print "Month: "$2 "\nYear: "$NF}'
# awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd
# awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd
參數說明:
    %s 字符類型
    %d 數值類型
    佔15字符
    - 表示左對齊,默認是右對齊
    printf默認不會在行尾自動換行,加\n

awk模式和動做

  任何awk語句都由模式和動做組成。模式部分決定動做語句什麼時候觸發及觸發事件。處理即對數據進行的操做。若是省略模式部分,動做將時刻保持執行狀態。模式能夠是任何條件語句或複合語句或正則表達式。模式包括兩個特殊字段 BEGIN和END。使用BEGIN語句設置計數和打印頭。BEGIN語句使用在任何文本瀏覽動做以前,以後文本瀏覽動做依據輸入文本開始執行。END語句用來在awk完成文本瀏覽動做後打印輸出文本總數和結尾狀態。編程語言

模式能夠是:正則表達式、比較表達式、條件表達式、算術運算符、邏輯操做符和複合模式、範圍模式等。函數

正則表達式:工具

匹配記錄(整行):
# awk '/^alice/'  /etc/passwd
# awk '!/root/' passwd

匹配字段:匹配操做符(~ !~)
# awk -F: '$1 ~ /^admin/'  /etc/passwd
# awk -F: '$NF !~ /nologin$/'  /etc/passwd

比較表達式:

  比較表達式採用對文本進行比較,只有當條件爲真,才執行指定的動做。比較表達式使用關係運算符,用於比較數字與字符串。

運算符            含義                            示例
<                小於                            x<y
<=               小於或等於                       x<=y
==               等於                            x==y
!=               不等於                          x!=y
>=               大於等於                        x>=y
>                大於                            x>y
# awk -F: '$3 == 0' /etc/passwd
# awk -F: '$3 < 10' /etc/passwd
# awk -F: '$7 == "/bin/bash"' /etc/passwd
# awk -F: '$1 == "root" ' /etc/passwd
# awk -F: '$1 ~ /admin/ ' /etc/passwd
# df -P | grep  '/' |awk '$4 > 25000'

條件表達式:

# awk -F: '$3>300 {print $0}' /etc/passwd
# awk -F: '{ if($3>300) print $0 }' /etc/passwd
# awk -F: '{ if($3>300) {print $0} }' /etc/passwd
# awk -F: '{ if($3>300) {print $3} else{print $1} }' /etc/passwd

算術運算:+ - * / %(模) ^(冪2^3)

能夠在模式中執行計算,awk都將按浮點數方式執行算術運算
# awk -F: '$3 * 10 > 500' /etc/passwd

邏輯操做符和複合模式:

&&        邏輯與        a&&b
||        邏輯或        a||b
!         邏輯非        !a
# awk -F: '$3 > 50 && $3 <=100' /etc/passwd
# awk -F: '$3 == 0 || $3 <=10' /etc/passwd
# awk -F: '!($3 == 0 || $3 <=10)' /etc/passwd

awk 腳本編程

條件判斷:

if語句:

//格式
{if(表達式){語句;語句;...}}

# awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd

# awk -F: '{if($3>0 && $3<1000){count++;}}  END{print count}' /etc/passwd    //統計系統用戶數

if...else語句:

//格式
{if(表達式){語句;語句;...}else{語句;語句;...}}

# awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd

# awk -F: '{if($3==0){count++} else{i++}} END{print "管理員個數: "count ; print "系統用戶數: "i}' /etc/passwd

if...else if...else語句:

//格式
{if(表達式1){語句;語句;...}else if(表達式2){語句;語句;...}else if(表達式3){語句;語句;...}else{語句;語句;...}}

# awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd

# awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理員個數: "i; print " 普通用個數: "k; print "系統用戶: "j}' /etc/passwd

循環:

while:

# awk 'BEGIN{i=1; while(i<=10){print i; i++}  }'
# awk -F: '{i=1; while(i<=10) {print $0;  i++}}' /etc/passwd        //將每行打印10次

for:

# awk 'BEGIN{for(i=1;i<=5;i++){print i} }'                          //C風格for

awk -F: '{for(i=1;i<=10;i++) print $0}' /etc/passwd                 //將每行打印10次

數組:

# awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd
root

# awk -F: '{username[i++]=$1} END{print username[1]}' /etc/passwd 
bin

# awk -F: '{username[i++]=$1} END{print username[0]}' /etc/passwd 
root

數組遍歷:

# awk -F: '{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}' /etc/passwd

# awk -F: '{username[++x]=$1} END{for(i=1;i<=x;i++) print i,username[i]}' /etc/passwd

# awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd

# awk -F: '{username[++x]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd

 練習

1. 統計/etc/passwd 中各類類型shell的數量
# awk -F: '{shells[$NF]++}END{ for(i in shells){print i,shells[i]}}' /etc/passwd

2. 網站訪問狀態統計 <當前時實狀態 netstat>
# netstat -ant |grep :80 |awk '{access_stat[$NF]++}END{for(i in access_stat){print i, access_stat[i]}}'
# netstat -ant |grep :80 |awk '{access_stat[$NF]++} END{for(i in access_stat ){print i,access_stat[i]}}' |sort -k2 -n |head
# ss -an |grep :80 |awk '{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}'
# ss -an |grep :80 |awk '{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}' |sort -k2 -rn

3. 統計當前訪問的每一個IP的數量 <當前時實狀態 netstat,ss>
# ss -an |grep :80 |awk -F":" '!/LISTEN/{ip_count[$(NF-1)]++} END{for(i in ip_count){print i,ip_count[i]}}' |sort -k2 -rn

4. 統計Apache/Nginx日誌中某一天的PV量  <統計日誌>
# grep '07/Aug/2012' access.log |wc -l

5. 統計Apache/Nginx日誌中某一天不一樣IP的訪問量 <統計日誌>
# grep '07/Dec/2018' access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn
# grep '07/Dec/2018' access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |awk '$2>100' |sort -k2

6. awk函數 統計用戶名爲4個字符的用戶
# awk -F: '$1~/^....$/{count++; print $1} END{print "count is: " count}' /etc/passwd
# awk -F: 'length($1)==4{count++; print $1} END{print "count is: "count}' /etc/passwd

7. 取得網卡IP(除ipv6之外的全部IP)
# ifconfig |awk '/[ ]inet[ ]/{print $2}'

8. 得到內存使用狀況
# free -m |awk 'NR==2{print $3*100/$2}'

9. 得到磁盤使用狀況
# df |awk '/\/$/{print $5}'

10. 清空本機的ARP緩存
# arp |awk '!/Address/{print "arp -d " $1}'|bash
# arp -n |awk '/^[0-9]/{print $1}' |xargs -I {} arp -d {}
相關文章
相關標籤/搜索