awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生成報告時,顯得尤其強大。簡單來講awk就是把文件逐行的讀入,以空格爲默認分隔符將每行切片,切開的部分再進行各類分析處理。php
awk有3個不一樣版本: awk、nawk和gawk,未做特別說明,通常指gawk,gawk 是 AWK 的 GNU 版本。mysql
AWK是一個優良的文本處理工具,Linux及Unix環境中現有的功能最強大的數據處理引擎之一,以Aho、Weinberger、Kernighan三位發明者名字首字母命名爲AWK,AWK是一個行級文本高效處理工具,AWK通過改進生成的新的版本有Nawk、Gawk,通常Linux默認爲Gawk,Gawk是 AWK的GNU開源免費版本。linux
AWK基本原理是逐行處理文件中的數據,查找與命令行中所給定內容相匹配的模式,若是發現匹配內容,則進行下一個編程步驟,若是找不到匹配內容,則 繼續處理下一行。程序員
awk '{pattern + action}' {filenames}正則表達式
儘管操做可能會很複雜,但語法老是這樣,其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令。花括號({})不須要在程序中始終出現,但它們用於根據特定的模式對一系列指令進行分組。 pattern就是要表示的正則表達式,用斜槓括起來。sql
awk語言的最基本功能是在文件或者字符串中基於指定規則瀏覽和抽取信息,awk抽取信息後,才能進行其餘文本操做。完整的awk腳本一般用來格式化文本文件中的信息。shell
一般,awk是以文件的一行爲處理單位的。awk每接收文件的一行,而後執行相應的命令,來處理文本。express
一、AWK基本語法參數詳解:apache
單引號’ ‘是爲了和shell命令區分開;編程
大括號{ }表示一個命令分組;
pattern是一個過濾器,表示匹配pattern條件的行才進行Action處理;
action是處理動做,常見動做爲Print;
使用#做爲註釋,pattern和action能夠只有其一,但不能二者都沒有。
二、AWK內置變量詳解:
$0 | 當前記錄(這個變量中存放着整個行的內容) |
$1~$n | 當前記錄的第n個字段,字段間由FS分隔 |
FS | 輸入字段分隔符 默認是空格或Tab |
NF | 當前記錄中的字段個數,就是有多少列 |
NR | 已經讀出的記錄數,就是行號,從1開始,若是有多個文件話,這個值也是不斷累加中。 |
FNR | 當前記錄數,與NR不一樣的是,這個值會是各個文件本身的行號 |
RS | 輸入的記錄分隔符, 默認爲換行符 |
OFS | 輸出字段分隔符, 默認也是空格 |
ORS | 輸出的記錄分隔符,默認爲換行符 |
FILENAME | 當前輸入文件的名字 |
有三種方式調用awk
1.命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可選的。 input-file(s) 是待處理的文件。
在awk中,文件的每一行中,由域分隔符分開的每一項稱爲一個域。一般,在不指名-F域分隔符的狀況下,默認的域分隔符是空格。
2.shell腳本方式
將全部的awk命令插入一個文件,並使awk程序可執行,而後awk命令解釋器做爲腳本的首行,一遍經過鍵入腳本名稱來調用。
至關於shell腳本首行的:#!/bin/sh
能夠換成:#!/bin/awk
3.將全部的awk命令插入一個單獨文件,而後調用:
awk -f awk-script-file input-file(s)
其中,-f選項加載awk-script-file中的awk腳本,input-file(s)跟上面的是同樣的。
過濾記錄
過濾條件爲:第三列的值爲0 && 第6列的值爲LISTEN)
1 2 3 4 5 |
|
須要表頭的話,咱們能夠引入內建變量NR:
1 2 3 4 5 6 |
|
再加上格式化輸出:
1 2 3 4 5 6 |
|
若是要輸出行號:
1 2 3 4 5 6 7 |
|
指定分隔符
$ awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd root 0 /root bin 1 /bin daemon 2 /sbin adm 3 /var/adm lp 4 /var/spool/lpd sync 5 /sbin shutdown 6 /sbin halt 7 /sbin
上面的命令也等價於:(-F的意思就是指定分隔符)
$ awk -F: '{print $1,$3,$6}' /etc/passwd
要指定多個分隔符,你能夠這樣來:
awk -F '[;:]'
一個以\t做爲分隔符輸出的例子(下面使用了/etc/passwd文件,這個文件是以:分隔的):
$ awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd root 0 /root bin 1 /bin daemon 2 /sbin adm 3 /var/adm lp 4 /var/spool/lpd sync 5 /sbin
字符串匹配
幾個字符串匹配的示例:
$ awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt 1 Local-Address Foreign-Address State 6 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2 9 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2 13 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1 18 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2 $ $ awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt 1 Local-Address Foreign-Address State 5 coolshell.cn:80 124.205.5.146:18245 TIME_WAIT 6 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2 9 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2 11 coolshell.cn:80 183.60.215.36:36970 TIME_WAIT 13 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1 15 coolshell.cn:80 183.60.212.163:51082 TIME_WAIT 18 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2
上面的第一個示例匹配FIN狀態, 第二個示例匹配WAIT字樣的狀態。其實 ~ 表示模式開始。/ /中是模式。這就是一個正則表達式的匹配。
awk能夠像grep同樣的去匹配第一行,就像這樣:
$ awk '/LISTEN/' netstat.txt tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN tcp 0 0 :::22 :::* LISTEN
使用 「/FIN|TIME/」 來匹配 FIN 或者 TIME :
$ awk '$6 ~ /FIN|TIME/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt 1 Local-Address Foreign-Address State 5 coolshell.cn:80 124.205.5.146:18245 TIME_WAIT 6 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2 9 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2 11 coolshell.cn:80 183.60.215.36:36970 TIME_WAIT 13 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1 15 coolshell.cn:80 183.60.212.163:51082 TIME_WAIT 18 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2
看看模式取反的例子:
$ awk '$6 !~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt 1 Local-Address Foreign-Address State 2 0.0.0.0:3306 0.0.0.0:* LISTEN 3 0.0.0.0:80 0.0.0.0:* LISTEN 4 127.0.0.1:9000 0.0.0.0:* LISTEN 7 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED 8 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED 10 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED 12 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED 14 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED 16 coolshell.cn:80 208.115.113.92:50601 LAST_ACK 17 coolshell.cn:80 123.169.124.111:49840 ESTABLISHED 19 :::22 :::* LISTEN
或是:
awk '!/WAIT/' netstat .txt |
折分文件
awk拆分文件很簡單,使用重定向就行了。下面這個例子,是按第6例分隔文件,至關的簡單(其中的NR!=1表示不處理表頭)
$ awk 'NR!=1{print > $6}' netstat.txt $ ls ESTABLISHED FIN_WAIT1 FIN_WAIT2 LAST_ACK LISTEN netstat.txt TIME_WAIT $ cat ESTABLISHED tcp 0 0 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED tcp 0 0 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED tcp 0 0 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED tcp 0 4166 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED tcp 0 0 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED tcp 0 0 coolshell.cn:80 123.169.124.111:49840 ESTABLISHED $ cat FIN_WAIT1 tcp 0 1 coolshell.cn:80 124.152.181.209:26825 FIN_WAIT1 $ cat FIN_WAIT2 tcp 0 0 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2 tcp 0 0 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2 tcp 0 0 coolshell.cn:80 117.136.20.85:50025 FIN_WAIT2 $ cat LAST_ACK tcp 0 1 coolshell.cn:80 208.115.113.92:50601 LAST_ACK
能夠把指定的列輸出到文件:
1 |
|
再複雜一點:(注意其中的if-else-if語句,可見awk實際上是個腳本解釋器)
awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt"; else if($6 ~ /LISTEN/) print > "2.txt"; else print > "3.txt" }' netstat.txt $ ls ?.txt 1.txt 2.txt 3.txt $ cat 1.txt tcp 0 0 coolshell.cn:80 124.205.5.146:18245 TIME_WAIT tcp 0 0 coolshell.cn:80 110.194.134.189:1032 ESTABLISHED tcp 0 0 coolshell.cn:80 123.169.124.111:49809 ESTABLISHED tcp 0 0 coolshell.cn:80 123.169.124.111:49829 ESTABLISHED tcp 0 0 coolshell.cn:80 183.60.215.36:36970 TIME_WAIT tcp 0 4166 coolshell.cn:80 61.148.242.38:30901 ESTABLISHED tcp 0 0 coolshell.cn:80 110.194.134.189:4796 ESTABLISHED tcp 0 0 coolshell.cn:80 183.60.212.163:51082 TIME_WAIT tcp 0 0 coolshell.cn:80 123.169.124.111:49840 ESTABLISHED $ cat 2.txt tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN $ cat 3.txt tcp 0 0 coolshell.cn:80 61.140.101.185:37538 FIN_WAIT2 tcp 0 0 coolshell.cn:80 116.234.127.77:11502 FIN_WAIT2 tcp 0 1 coolshell.cn:80 124.152.181.209:26825
統計
下面的命令計算全部的C文件,CPP文件和H文件的文件大小總和。
$ ls -l *.cpp *.c *.h | awk '{sum+=$5} END {print sum}' 2511401
一個統計各個connection狀態的用法:(咱們能夠看到一些編程的影子了,你們都是程序員我就不解釋了。注意其中的數組的用法)
$ awk 'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}' netstat.txt TIME_WAIT, 3 FIN_WAIT1, 1 ESTABLISHED, 6 FIN_WAIT2, 3 LAST_ACK, 1 LISTEN, 4
再來看看統計每一個用戶的進程的佔了多少內存(注:sum的RSS那一列)
$ ps aux | awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}' dbus, 540KB mysql, 99928KB www, 3264924KB root, 63644KB hchen, 6020KB
END的意思是「處理完全部的行的標識」,即然說到了END就有必要介紹一下BEGIN,這兩個關鍵字意味着執行前和執行後的意思,語法以下:
有這麼一個文件(學生成績表):
$ cat score.txt Marry 2143 78 84 77 Jack 2321 66 78 45 Tom 2122 48 77 71 Mike 2537 87 97 95 Bob 2415 40 57 62
awk腳本以下(我沒有寫有命令行上是由於命令行上不易讀,另外也在介紹另外一種用法):
$ cat cal.awk #!/bin/awk -f #運行前 BEGIN { math = 0 english = 0 computer = 0 printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n" printf "---------------------------------------------\n" } #運行中 { math+=$3 english+=$4 computer+=$5 printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5 } #運行後 END { printf "---------------------------------------------\n" printf " TOTAL:%10d %8d %8d \n", math, english, computer printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR }
執行結果:(也能夠這樣運行 ./cal.awk score.txt)
$ awk -f cal.awk score.txt NAME NO. MATH ENGLISH COMPUTER TOTAL --------------------------------------------- Marry 2143 78 84 77 239 Jack 2321 66 78 45 189 Tom 2122 48 77 71 196 Mike 2537 87 97 95 279 Bob 2415 40 57 62 159 --------------------------------------------- TOTAL: 319 393 350 AVERAGE: 63.80 78.60 70.00
環境變量
即然說到了腳本,咱們來看看怎麼和環境變量交互:(使用-v參數和ENVIRON,使用ENVIRON的環境變量須要export)
$ x=5 $ y=10 $ export y $ echo $x $y 5 10 $ awk -v val=$x '{print $1, $2, $3, $4+val, $5+ENVIRON["y"]}' OFS="\t" score.txt Marry 2143 78 89 87 Jack 2321 66 83 55 Tom 2122 48 82 81 Mike 2537 87 102 105 Bob 2415 40 62 72
幾個小例子:
#從file文件中找出長度大於80的行 awk 'length>80' file #按鏈接數查看客戶端IP netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr #打印99乘法表 seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}'
$0 則表示全部域
$1 表示第一個域;
$n 表示第n個域;
默認域分隔符是」空白鍵」 或 「鍵」,
因此$1表示登陸用戶,$3表示登陸用戶ip
awk 具備 grep 和 sed命令的特性,同時 AWK針對列進行匹配
Usage: awk [options] -f progfile [--] file ... Usage: awk [options] [--] 'program' file ...
-F fs
fs指定輸入分隔符,fs能夠是字符串或正則表達式;如-F ":"
-vvar=value
賦值一個用戶定義變量,將外部變量傳遞給awk
-f progfile
從腳本文件中讀取awk命令
-m[fr]val
對val值設置內在限制;
-mf選項
限制分配給val的最大塊數目;
-mr選項
限制記錄最大數目;
此選項爲awk的擴展功能,在標準awk中不適用;
假設last -n 5的輸出以下
# last -n 5 僅取出前五行
root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in
root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)
dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)
root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
若是隻是顯示最近登陸的5個賬號
#last -n 5 | awk '{print $1}'
root
root
root
dmtsai
root
awk工做流程是這樣的:讀入有’n’換行符分割的一條記錄,而後將記錄按指定的域分隔符劃分域,填充域,$0則表示全部域,$1表示第一個域,$n表示第n個域。默認域分隔符是」空白鍵」 或 「鍵」,因此$1表示登陸用戶,$3表示登陸用戶ip,以此類推。
若是隻是顯示/etc/passwd的帳戶
#cat /etc/passwd |awk -F ':' '{print $1}'
root
daemon
bin
sys
這種是awk+action的示例,每行都會執行action{print $1}。
-F指定域分隔符爲’:’。
若是隻是顯示/etc/passwd的帳戶和帳戶對應的shell,而帳戶與shell之間以tab鍵分割
#cat /etc/passwd |awk -F ':' '{print $1"t"$7}'
root /bin/bash
daemon /bin/sh
bin /bin/sh
sys /bin/sh
若是隻是顯示/etc/passwd的帳戶和帳戶對應的shell,而帳戶與shell之間以逗號分割,並且在全部行添加列名name,shell,在最後一行添加」blue,/bin/nosh」。
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh
awk工做流程是這樣的:先執行BEGING,而後讀取文件,讀入有/n換行符分割的一條記錄,而後將記錄按指定的域分隔符劃分域,填充域,$0則表示全部域,$1表示第一個域,$n表示第n個域,隨後開始執行模式所對應的動做action。接着開始讀入第二條記錄······直到全部的記錄都讀完,最後執行END操做。
搜索/etc/passwd有root關鍵字的全部行
#awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
這種是pattern的使用示例,匹配了pattern(這裏是root)的行纔會執行action(沒有指定action,默認輸出每行的內容)。
搜索支持正則,例如找root開頭的: awk -F: ‘/^root/’ /etc/passwd
搜索/etc/passwd有root關鍵字的全部行,並顯示對應的shell
# awk -F: '/root/{print $7}' /etc/passwd
/bin/bash
這裏指定了action{print $7}
awk有許多內置變量用來設置環境信息,這些變量能夠被改變,下面給出了最經常使用的一些變量。
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk瀏覽的文件名
FNR 瀏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令行 -F選項
NF 瀏覽記錄的域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 控制記錄分隔符
此外,$0變量是指整條記錄。$1表示當前行的第一個域,$2表示當前行的第二個域,……以此類推
統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:
#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
使用printf替代print,可讓代碼更加簡潔,易讀
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%sn",FILENAME,NR,NF,$0)}'/etc/passwd
awk中同時提供了print和printf兩種打印輸出的函數。
其中print函數的參數能夠是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。若是沒有逗號,參數就串聯在一塊兒而沒法區分。這裏,逗號的做用與輸出文件的分隔符的做用是同樣的,只是後者是空格而已。
printf函數,其用法和c語言中printf基本類似,能夠格式化字符串,輸出複雜時,printf更加好用,代碼更易懂。
變量和賦值
除了awk的內置變量,awk還能夠自定義變量。
下面統計/etc/passwd的帳戶人數
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
......
user count is 40
count是自定義變量。以前的action{}裏都是隻有一個print,其實print只是一個語句,而action{}能夠有多個語句,以;號隔開。
這裏沒有初始化count,雖然默認是0,可是穩當的作法仍是初始化爲0:
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
[start]user count is 0
root:x:0:0:root:/root:/bin/bash
...
[end]user count is 40
統計某個文件夾下的文件佔用的字節數
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'
[end]size is 8657198
若是以M爲單位顯示:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.25889 M
注意,統計不包括文件夾的子目錄。
條件語句
awk中的條件語句是從C語言中借鑑來的,見以下聲明方式:
if (expression) {
statement;
statement;
... ...
}
if (expression) {
statement;
} else {
statement2;
}
if (expression) {
statement1;
} else if (expression1) {
statement2;
} else {
statement3;
}
統計某個文件夾下的文件佔用的字節數,過濾4096大小的文件(通常都是文件夾):
ls -l | awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.22339 M
循環語句
awk中的循環語句一樣借鑑於C語言,支持while、do/while、for、break、continue,這些關鍵字的語義和C語言中的語義徹底相同。
數組
由於awk中數組的下標能夠是數字和字母,數組的下標一般被稱爲關鍵字(key)。值和關鍵字都存儲在內部的一張針對key/value應用hash的表格裏。因爲hash不是順序存儲,所以在顯示數組內容時會發現,它們並非按照你預料的順序顯示出來的。數組和變量同樣,都是在使用時自動建立的,awk也一樣會自動判斷其存儲的是數字仍是字符串。通常而言,awk中的數組用來從記錄中收集信息,能夠用於計算總和、統計單詞以及跟蹤模板被匹配的次數等等。
顯示/etc/passwd的帳戶
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i ' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
......
這裏使用for循環遍歷數組
## $1 $2...$n 表示字段;$0 表示全部字段 head -n2 test.txt | awk -F ":" '{print $0}' head -n2 test.txt | awk -F ":" '{print $1}'## 輸入字段分隔符 head -n2 test.txt | awk -F ":" '{print $1"#"$2"#"$3}' head -n2 test.txt | awk -F ":" '{OFS="#"}{print $1,$2,$3}'## 字符串過濾【具備grep過濾功能】 awk -F ":" '/root/' test.txt ## 匹配字符串爲root的行 awk -F ":" '$1 ~/root/' test.txt ## 匹配第一字段包含root的行 ## awk的數學運算 awk -F ":" '$3>$4' /etc/passwd awk -F ":" '$3>800 || $7=="/bin/bash"' /etc/passwd awk -F ":" '$7!="/sbin/nologin"' /etc/passwd ## if判斷用例 awk -F ":" '{if($1=="root"){print $0} }' text awk -F ":" '{if($3>=20){print $3}}' text## awk的循環 awk -F ":" '{(tot=tot+$3)}; END {print tot}' text
打印行號【awk/grep實現】
## awk寫法 [root@shell awk]# awk -F ":" '/root/{print NR":"$0}' /etc/passwd 1:root:x:0:0:root:/root:/bin/bash 10:operator:x:11:0:operator:/root:/sbin/nologin ## grep寫法 [root@shell awk]# grep -n 'root' /etc/passwd 1:root:x:0:0:root:/root:/bin/bash 10:operator:x:11:0:operator:/root:/sbin/nologin
## awk寫法
[root@shell awk]# awk -F ":" '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
## grep寫法
[root@shell awk]# grep 'root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@shell awk]# awk -F ":" '$1 ~/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
rootaaaaa:x:0:0:root:/root:/bin/bash
irootaaaaa:x:0:0:root:/root:/bin/bash
## awk寫法(一)
[root@shell awk]# awk -F ":" '/root|bash/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
## awk寫法(二)
[root@shell awk]# awk -F ":" '/root/ || /bash/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
## grep寫法
[root@shell awk]# grep -E "root|bash" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
## 匹配 $3等於字符串0 [root@shell awk]# awk -F ":" '$3=="0"' /etc/passwd root:x:0:0:root:/root:/bin/bash## 匹配 $3 大於等於字符串 10 [root@ansible-master awk]# head -n 5 text |awk -F ":" '$3>="10"' rootaaaaa:x:10:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin## 匹配 $3 大於等於數字 10 [root@ansible-master awk]# head -n 5 text |awk -F ":" '$3>=10' rootaaaaa:x:10:0:root:/root:/bin/bash## 匹配$7字段 不等於字符串·/bin/nologin· [root@ansible-master awk]# head -n 5 text |awk -F ":" '$7!="/bin/nologin"' root:x:0:0:root:/root:/bin/bash rootaaaaa:x:10:0:root:/root:/bin/bash irootaaaaa:x:01:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin
## 方法1 [root@shell awk]# awk -F ":" '{OFS="#"} /root|bash/ {print $1,$2,$5}' /etc/passwd root#x#root operator#x#operator## 方法2 [root@shell awk]# awk -F ":" '/root|bash/ {print $1"#"$2"#"$5}' /etc/passwd root#x#root operator#x#operator
[root@shell awk]# awk -F ":" '{OFS="#"}{if($3>800){print $1,$3,$7}}' /etc/passwd polkitd#999#/sbin/nologin chrony#998#/sbin/nologin jenkins#997#/bin/false saslauth#996#/sbin/nologin
NR 表示,只打印行號
$NR 表示,根據當前行號打印相應字段(好比:第1行,打印 $1字段;第2行,打印$2字段)
## NR 表示,只打印行號 [root@ansible-master awk]# head -6 text | awk -F ":" '{print NR, $0}' 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync## 匹配NR 大於 20 的行 [root@ansible-master awk]# awk -F ":" 'NR>20 {print NR,$0}' text 21 chrony:x:998:996::/var/lib/chrony:/sbin/nologin 22 jenkins:x:997:993:Jenkins Automation Server:/var/lib/jenkins:/bin/false 23 saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin 24 mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin 25 smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin## $NR 表示,根據當前行號打印相應的字段 [root@ansible-master awk]# head -6 text | awk -F ":" '{print $NR, $0}' root root:x:0:0:root:/root:/bin/bashx bin:x:1:1:bin:/bin:/sbin/nologin 2 daemon:x:2:2:daemon:/sbin:/sbin/nologin 4 adm:x:3:4:adm:/var/adm:/sbin/nologin lp lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin /sbin sync:x:5:0:sync:/sbin:/bin/sync
awk的條件判斷使用
192 81 999## 判斷,若是$1字段 等於 字符串root 則打印 [root@ansible-master awk]# awk -F ":" '{if($1=="root"){print $0} }' text root:x:0:0:root:/root:/bin/bash## 判斷,若是$3字段 大於 數字20 則打印 [root@ansible-master awk]# awk -F ":" '{if($3>=20){print $3}}' text 99
4707## 求和 文件全部第3列 [root@ansible-master awk]# awk -F ":" '{(tot=tot+$3)}; END {print tot}' text
常見問題 :
一、下面統計/etc/passwd的帳戶人數
#awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
二、統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:
#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
三、搜索/etc/passwd有root關鍵字的全部行,並顯示對應的shell
# awk -F: '/root/{print $7}' /etc/passwd
四、只是顯示最近登陸的5個賬號
#last -n 5 | awk '{print $1}'
五、顯示/etc/passwd的帳戶
#cat /etc/passwd |awk -F ':' '{print $1}'
六、只是顯示/etc/passwd的帳戶和帳戶對應的shell,而帳戶與shell之間以tab鍵分割
#cat /etc/passwd |awk -F ':' '{print $1"t"$7}'
七、只是顯示/etc/passwd的帳戶和帳戶對應的shell,而帳戶與shell之間以逗號分割,並且在全部行添加列名name,shell,在最後一行添加」blue,/bin/nosh」。
#cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
八、搜索/etc/passwd有root關鍵字的全部行
#awk -F: '/root/' /etc/passwd
九、使用printf替代print,可讓代碼更加簡潔,易讀
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%sn",FILENAME,NR,NF,$0)}'/etc/passwd
十、下面統計/etc/passwd的帳戶人數
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
......
user count is 40
十一、沒有初始化count,默認是0,把他們都初始化爲0:
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
[start]user count is 0
root:x:0:0:root:/root:/bin/bash
...
[end]user count is 40
十二、統計某個文件夾下的文件佔用的字節數
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'
[end]size is 8657198
1三、若是以M爲單位顯示:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.25889 M
注意,統計不包括文件夾的子目錄。
1四、統計某個文件夾下的文件佔用的字節數,過濾4096大小的文件(通常都是文件夾):
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.22339 M
1五、顯示/etc/passwd的帳戶
#awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i ' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
1六、AWK打印硬盤設備名稱,默認以空格爲分割:
df -h | awk ‘{print $1}’
1七、AWK以空格、冒號、\t、分號爲分割:
awk -F ‘[ :\t;]’ ‘{print $1}’ jfedu.txt
1八、AWK以冒號分割,打印第一列,同時將內容追加到/tmp/awk.log下:
awk -F ‘[ :\t;]’ ‘{print $1}’ jfedu.txt
1九、打印jfedu.txt文件中的第3行至第5行,NR表示打印行,$0表示文本全部域:
awk ‘NR==3,NR==5 {print}’ jfedu.txt
awk ‘NR==3,NR==5 {print $0}’ jfedu.txt
20、打印jfedu.txt文件中,長度大於80的行號:
awk ‘length($0)>80 {print NR}’ jfedu.txt
2一、AWK引用Shell變量,使用-v或者雙引號+單引號便可:
awk -v STR=hello ‘{print STR,$NF}’ jfedu.txt
STR=」hello」;echo| awk ‘{print 「‘${STR}'」;}’
2二、Awk統計服務器狀態鏈接數:
netstat -an | awk ‘/tcp/ {s[$NF]++} END {for(a in s) {print a,s[a]}}’
netstat -an | awk ‘/tcp/ {print $NF}’ | sort | uniq -c
2三、查看每個IP訪問了多少個頁面:
awk '{++S[$1]} END {for (a in S) print a,S[a]}' log_file > log.txt sort -n -t ' ' -k 2 log.txt 配合sort進一步排序
2四、將每一個IP訪問的頁面數進行從小到大排序:
awk '{++S[$1]} END {for (a in S) print S[a],a}' log_file | sort -n
2五、去掉搜索引擎統計的頁面:
awk '{print $12,$1}' log_file | grep ^"Mozilla | awk '{print $2}' |sort | uniq | wc -l
2六、查看2015年8月16日14時這一個小時內有多少IP訪問:
awk '{print $4,$1}' log_file | grep 16/Aug/2015:14 | awk '{print $2}'| sort | uniq | wc -l
2七、查看訪問前十個ip地址
awk '{print $1}' |sort|uniq -c|sort -nr |head -10 access_log
2八、niq -c 至關於分組統計並把統計數放在最前面
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九、訪問次數最多的10個文件或頁面
cat log_file|awk '{print $11}'|sort|uniq -c|sort -nr | head -10 cat log_file|awk '{print $11}'|sort|uniq -c|sort -nr|head -20 awk '{print $1}' log_file |sort -n -r |uniq -c | sort -n -r | head -20
30、訪問量最大的前20個ip
經過子域名訪問次數,依據referer來計算,稍有不許
cat access.log | awk '{print $11}' | sed -e ' s/http:////' -e ' s//.*//' | sort | uniq -c | sort -rn | head -20
3一、列出傳輸大小最大的幾個文件
cat www.access.log |awk '($7~/.php/){print $10 " " $1 " " $4 " " $7}'|sort -nr|head -100
3二、列出輸出大於200000byte(約200kb)的頁面以及對應頁面發生次數
cat www.access.log |awk '($10 > 200000 && $7~/.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100
3三、若是日誌最後一列記錄的是頁面文件傳輸時間,則有列出到客戶端最耗時的頁面
cat www.access.log |awk '($7~/.php/){print $NF " " $1 " " $4 " " $7}'|sort -nr|head -100
3四、列出最最耗時的頁面(超過60秒的)的以及對應頁面發生次數
cat www.access.log |awk '($NF > 60 && $7~/.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100
3五、列出傳輸時間超過 30 秒的文件
cat www.access.log |awk '($NF > 30){print $7}'|sort -n|uniq -c|sort -nr|head -20
3六、列出當前服務器每一進程運行的數量,倒序排列
ps -ef | awk -F ' ' '{print $8 " " $9}' |sort | uniq -c |sort -nr |head -20
3七、分析日誌文件下 2012-05-04 訪問頁面最高 的前20個 URL 並排序
cat access.log |grep '04/May/2012'| awk '{print $11}'|sort|uniq -c|sort -nr|head -20
3八、查詢受訪問頁面的URL地址中 含有 www.abc.com 網址的 IP 地址
cat access_log | awk '($11~/www.abc.com/){print $1}'|sort|uniq -c|sort -nr
3九、獲取訪問最高的10個IP地址 同時也能夠按時間來查詢
cat linewow-access.log|awk '{print $1}'|sort|uniq -c|sort -nr|head -10
40、時間段查詢日誌時間段的狀況
cat log_file | egrep '15/Aug/2015|16/Aug/2015' |awk '{print $1}'|sort|uniq -c|sort -nr|head -10
4一、分析 2015/8/15 到 2015/8/16 訪問」/index.php?g=Member&m=Public&a=sendValidCode」的IP倒序排列
cat log_file | egrep '15/Aug/2015|16/Aug/2015' | awk '{if($7 == "/index.php?g=Member&m=Public&a=sendValidCode") print $1,$7}'|sort|uniq -c|sort -nr
4二、($7~/.php/) $7裏面包含.php的就輸出,本句的意思是最耗時的一百個PHP頁面
cat log_file |awk '($7~/.php/){print $NF " " $1 " " $4 " " $7}'|sort -nr|head -100
4三、列出最最耗時的頁面(超過60秒的)的以及對應頁面發生次數
cat access.log |awk '($NF > 60 && $7~/.php/){print $7}'|sort -n|uniq -c|sort -nr|head -100
4四、統計網站流量(G)
cat access.log |awk '{sum+=$10} END {print sum/1024/1024/1024}'
4五、統計404的鏈接
awk '($9 ~/404/)' access.log | awk '{print $9,$7}' | sort
4六、統計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
4七、每秒併發
watch "awk '{if($9~/200|30|404/)COUNT[$4]++}END{for( a in COUNT) print a,COUNT[a]}' log_file|sort -k 2 -nr|head -n10"
4八、帶寬統計
cat apache.log |awk '{if($7~/GET/) count++}END{print "client_request="count}'
4九、找出某天訪問次數最多的10個IP
cat /tmp/access.log | grep "20/Mar/2011" |awk '{print $3}'|sort |uniq -c|sort -nr|head
50、當天ip鏈接數最高的ip都在幹些什麼
cat access.log | grep "10.0.21.17" | awk '{print $8}' | sort | uniq -c | sort -nr | head -n 10
5一、小時單位裏ip鏈接數最多的10個時段
awk -vFS="[:]" '{gsub("-.*","",$1);num[$2" "$1]++}END{for(i in num)print i,num[i]}' log_file | sort -n -k 3 -r | head -10
5二、找出訪問次數最多的幾個分鐘
awk '{print $1}' access.log | grep "20/Mar/2011" |cut -c 14-18|sort|uniq -c|sort -nr|hea
5三、取5分鐘日誌
if [ $DATE_MINUTE != $DATE_END_MINUTE ] ;then #
則判斷開始時間戳與結束時間戳是否相等
START_LINE=sed -n "/$DATE_MINUTE/=" $APACHE_LOG|head -n1
#若是不相等,則取出開始時間戳的行號,與結束時間戳的行號
查看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," ",state[key]}' netstat -n | awk '/^tcp/ {++arr[$NF]};END {for(k in arr) print k," ",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 netstat -ant|awk '/ip:80/{split($5,ip,":");++S[ip[1]]}END{for (a in S) print S[a],a}' |sort -n netstat -ant|awk '/:80/{split($5,ip,":");++S[ip[1]]}END{for (a in S) print S[a],a}' |sort -rn|head -n 10 awk 'BEGIN{printf ("http_code count_num")}{COUNT[$10]++}END{for (a in COUNT) printf a" "COUNT[a]" "}'
5四、查找請求數前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
5五、用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
5六、根據端口列進程
netstat -ntlp | grep 80 | awk '{print $7}' | cut -d/ -f1
5七、Linux命令分析當前的連接情況
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
5八、watch "netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'"
# 經過watch能夠一直監控
LAST_ACK 5 #關閉一個TCP鏈接須要從兩個方向上分別進行關閉,雙方都是經過發送FIN來表示單方向數據的關閉,當通訊雙方發送了最後一個FIN的時候,發送方此時處於LAST_ACK狀態,當發送方收到對方的確認(Fin的Ack確認)後才真正關閉整個TCP鏈接;
SYN_RECV 30 # 表示正在等待處理的請求數;
ESTABLISHED 1597 # 表示正常數據傳輸狀態;
FIN_WAIT1 51 # 表示server端主動要求關閉tcp鏈接;
FIN_WAIT2 504 # 表示客戶端中斷鏈接;
TIME_WAIT 1057 # 表示處理完畢,等待超時結束的請求數;
5九、
60、
6一、
6二、
6三、
6四、
6五、
6六、
6七、
6八、
6九、
70、
參考連接 :
10分鐘學會 linux awk命令 : https://mp.weixin.qq.com/s/a8inpw8TrEOw7rxVgYQDwg
SHELL——awk報告生成器(基礎用法) : https://blog.csdn.net/qq_42036824/article/details/85225853