1. 簡介
來由與做用 awk是由Aho, Weinberger, Kernighan三位大牛開發的程序,用於報告生成器,格式化文本輸出,可接收標準輸入
版本php
New awk(nawk)
GNU awk( gawk),centos使用的爲gawk
運行原理css
分割符、域和記錄linux
awk執行時,由分隔符分隔的字段(域)標記1 , 1, 0爲全部域,注意:和shell中變量$符含義不一樣
文件讀入內存空間的每一行稱爲記錄,文本中的一行能夠爲多個記錄
省略action,則默認執行 print $ 0 的操做
工做原理nginx
執行BEGIN{action;… }語句塊中的語句
從文件或標準輸入(stdin)讀取一個記錄到內存空間,執行pattern{ action;… }語句塊,匹配預約義的模式,若是不匹配就不處理,匹配後按照預先規定好的分隔符切割成若干字段,分割成功後,系統會對這些列分配一個域標識$ 1..$ n,直到文件所有被讀取完畢。
當讀至輸入流末尾時,執行END{action;…}語句塊web
BEGIN語句塊在awk開始從輸入流中讀取行以前被執行,這是一個可選的語句塊,好比變量初始化、打印輸出表格的表頭等語句一般能夠寫在BEGIN語句塊中
END語句塊在awk從輸入流中讀取完全部的行以後即被執行,好比打印全部行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊
pattern語句塊中的通用命令是最重要的部分,也是可選的。若是沒有提供pattern語句塊,則默認執行{ print },即打印每個讀取到的行,awk讀取的每一行都會執行該語句塊
2. 基本用法
格式: awk [options] var=value ‘program’ file…
選項(options):正則表達式
-v var=value: 自定義變量
-f programfile: 讀取文件中的程序 awk [options] var=value -f programfile file…
-F:指明輸入時用到的字段分隔符,分隔符能夠指定多個sql
示例:指定[;]爲記錄分隔符,下例爲2個記錄a:b@c:d與1:2@3
1:指定[:]爲字段分割符
$echo "a:b@c:d;1:2@3"|awk -v RS=";" -F":" '{print $1,$3}'
a d
1
2:指定[@:]爲字段分割符
$echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"[@:]" '{print $1,$3}'
a c 兩個分隔符都起做用,c爲第3個字段
1 3
3:以擴展正則表達式方法表示也能夠
$echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"@|:" '{print $1,$3}'
program 爲awk本身的語法,一般是被單引號或雙引號中,建議使用單引號,由於雙引號在程序中會在字符串上用,避免混用shell
格式:
BEGIN語句塊、可以使用模式匹配的通用語句塊、END語句塊,共3部分組成 ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }’
經常使用格式: pattern{action statements;..}
釋義pattern和action:
pattern部分決定動做語句什麼時候觸發及觸發事件
action statements對數據進行處理,放在{ }內指明
action格式: {print|printf item1, item2, …}
要點:
逗號分隔符
輸出的各item能夠字符串,也能夠是數值;當前記錄的字段、變量或awk的表達式
如省略item,至關於print $0
示例 例如:打印出/etc/passwd文件的第1和第3行express
awk -F:
'{print $1 ,$3 }' /etc/passwd
3. awk變量
變量:分爲內置和自定義變量,只要對變量賦值,就要放在選項-v的後面apache
3.1 內置變量
示例1:定義FS=’:’,在(程序)中調用變量 $awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd named:25
示例2:一次引用多個變量,中間須要使用逗號隔開 $awk -v FS=: '{print $1FS,FS,FS$3}' /etc/passwd named: : :25
示例3:還能夠引用shell中的變量,先聲明fs=:,而後用awk調用 $fs=:;awk -v FS="$fs" '{print $1FS$3}' /etc/passwd named:25
OFS(output field separator):指定輸出字段分隔符,默認爲空白字符
示例:以###做爲字段分隔符 $awk -F":" -v OFS=### '{print $1,$3,$2}' /etc/passwd named###25###x
RS(record separator):輸入記錄分隔符,指定輸入時的換行符
示例:建立文本,以下awk.txt所示,[@,!,?]與[1,2,3,4]以及[A,B,C\naa,bb,cc],以[;]分隔開
1. 建立實驗文本
$cat awk.txt
@,!,?;1,2,3,4;A,B,C
aa,bb,cc
2. 指定輸入字段分隔符爲[,],輸出字段分隔符爲[==],輸入記錄分隔符爲[;]
$awk -v FS="," -v OFS="==" -v RS=";" '{print $3,$4}' awk.txt
?== <==第一個記錄@,!,?沒有第4個字段
3==4 <==第二個記錄1,2,3,4,顯示後兩個
C <==第三個記錄,保留原有格式換行,C\naa爲第三個字段
aa==bb
ORS:輸出記錄分隔符,輸出時用指定符號代替換行符
承上例,每條記錄輸出時默認爲換行處理,能夠經過ORS指定
$awk -v FS="," -v OFS="==" -v RS=";" -v ORS="***" '{print $3,$4}' awk.txt
?==***3==4***C <==記錄輸出時以指定的符號代替原回車換行
aa==bb***
NF:字段數量
$awk -F: '{print NF}' /etc/passwd
7 <==統計字段數量
$awk -F: '{print $(NF-6)}' /etc/passwd
named <==顯示第一列內容,至關於$1,要用括號括起來
NR:記錄號
$awk -F: '{print NR,$1}' /etc/passwd
45 named <==至關於多了個行號
FNR:各文件分別計數,記錄號
$awk -F: '{print NR,$1}' /etc/passwd /etc/group
121 named <==一共有多少記錄
處理多個文件時,使用NR會將記錄號累計,不會按文件分開,這時須要使用FNR
$awk -F: '{print FNR,$1}' /etc/passwd /etc/group
45 named <==/etc/passwd文件最後一個記錄
76 named <==/etc/group文件最後一個記錄
FILENAME:當前文件名 承上例,若是以爲顯示不清楚,能夠加上文件名
$awk -F: '{print FNR,FILENAME,$1}' /etc/passwd /etc/group
76 /etc/group named
ARGC:命令行參數的個數
$awk '{print ARGC}' /etc/passwd /etc/group
3 <==統計命令行參數的個數
ARGV:數組,保存的是命令行所給定的各參數 上例爲何是3個參數?使用ARGV查看各參數
$awk '{print ARGV[0] }' /etc/passwd /etc/group
awk <==將awk算爲了一個參數
$awk '{print ARGV[2] }' /etc/passwd /etc/group
/etc/group <==第三個參數
3.2 自定義變量(區分字符大小寫)
格式
-v var=value 例如 -v NAME=USERNAME
直接在程序中定義變量{NAME=USERNAME;print…}
示例
示例:使用格式1自定義
$awk -F: -v USER=「username」 -v UID=「userid」 ‘{print USER":"$1,UID":"$3}’ /etc/passwd /etc/group
username:named userid:25 這樣顯示不是很清晰,還記得記錄分隔符嗎
$awk -F: -v USER=「username」 -v UID=「userid」 -v ORS="\n------\n" ‘{print USER":"$1"\n"UID":"$3}’ /etc/passwd /etc/group
username:screen userid:84
username:named userid:25
示例:使用格式2自定義
$awk -F: -v ORS="\n------\n" '{USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3}' /etc/passwd /etc/group
示例:將action放入文件,使用-f選項
1. 將程序內容放入文件awk2.txt 中
$cat awk2.txt
{USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3}
2. 執行如下命令,寫入文件的程序就不須要單引號了
$awk -F: -v ORS="\n------\n" -f awk2.txt /etc/passwd
4. action中的printf命令
格式 printf 「FORMAT」, item1, item2, …
注意事項
必須指定FORMAT
不會自動換行,須要顯式給出換行控制符,\n
FORMAT中須要分別爲後面每一個item指定格式符
格式符:與item對應
符號
釋義
%c
顯示字符的ASCII碼
%d, %i
顯示十進制整數
%c
顯示字符的ASCII碼
%e, %E
顯示科學計數法數值
%g, %G
以科學計數法或浮點形式顯示數值
%s
顯示字符串
%u
無符號整數
%%
顯示%自身
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後精度,如%3.1f
-: 左對齊(默認右對齊),如%-15s
+:顯示數值的正負符號,如%+d
示例
示例1: 取出/etc/passwd第1,3行,並在其前分別加Username和UID
awk -F: ‘{
printf "Username: %- 15s,UID:%d \n" ,
$1 ,
$3 }’ /etc/passwd
示例2:%s對應$ 1,表示文件第一行爲字符串,在%與s中間能夠添加參數[-]表示左對齊[20]表示第一列所佔寬度,同理%-4d表示$2佔4個字符寬度左對齊
$awk -F:
'{printf"|%-20s %-4d|\n---------------------------\n",$1,$3 }' /etc/passwd
示例3:在這裏演示一下BEGIN的效果,添加表頭,效果以下
$awk -F:
'BEGIN{print "|user |ID |\n----------------------------"}' '{printf"|%-20s |%-4d|\n----------------------------\n",$1,$3 }' /etc/passwd
示例4:小數處理示例
1 :
$echo "3.1415 1.15926" |awk
'{printf "%2.2f;%1.4f",$1,$2}'
3.14 ;
1.1593
%2 .
2 f第一個
2 表示寬度,第二個
2 個小數點保留位數
%1 .
4 f最後一位達到
6 時會進位
2 :
$echo "3.1415 1.15925" |awk
'{printf "%2.2f;%1.4f",$1,$2}'
3.14 ;
1.1592
%1 .
4 f最後一位值爲
5 時不會進位
3 :
$echo "3.1415 11.15925" |awk
'{printf "%2.2f;%10.4f",$1,$2}'
3.14 ;
** *11 .
1593 <==這裏爲了顯示效果,以
** *代 替空格,共
10 個寬度
%10 .
4 f寬度起做用了,說明寬度若是小於實際佔用值,會以實際寬度爲準
5. 操做符
5.1 算術操做符:
操做符
定義
+
加
-
減
*
乘
/
除
%
取餘
^
冪
-x
轉換爲負數
+x
轉換爲數值
5.2 賦值操做符:
操做符
定義
=
賦值
+=
將加的結果賦給變量
-=
將減的結果賦給變量
*=
將乘的結果賦給變量
/=
將除的結果賦給變量
%=
將取餘的結果賦給變量
^=
將取冪的結果賦給變量
++
變量加1
–
變量減1
示例:下面兩語句有何不一樣 awk ‘BEGIN{i=0;print ++i,i}’ awk ‘BEGIN{i=0;print i++,i}’
[root
@hai7 ~]
$awk 'BEGIN{i=10;print ++i,i}'
11 11
先遞增,再將遞增值打印
[root
@hai7 ~]
$awk 'BEGIN{i=10;print i++,i}'
10 11
先打印i值,再遞增
5.4 比較操做符:
操做符
定義
==
等於
!=
不等於
>
大於
>=
大於等於
<
小於
<=
小於等於
5.5 模式匹配符
操做符
定義
~
左邊是否和右邊匹配
!~
是否不匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1 :篩選文件/etc/passwd中包含root的行
[root
@hai7 ~]
$awk -
F : '$0 ~ /root/{print NR$1}' /etc/passwd
1 root
10 operator
2 :篩選文件/etc/passwd中以root開頭的行
[root
@hai7 ~]
$awk -
F : '$0 ~ "^root"{print NR,$1}' /etc/passwd
1 root
3 :篩選文件/etc/passwd中不包含root的行
[root
@hai7 ~]
$awk -
F : '$0 !~ /root/{print NR,$1}' /etc/passwd
2 bin
9 mail
11 games
4 :篩選第三字段爲
0 的行
[root
@hai7 ~]
$awk -
F : '$3==0' /etc/passwd
root: x: 0 : 0 :root :/root :/bin/bash
5.6 邏輯操做符:與&&,或||,非!
1 :篩選第 3 個字段大於等於 50 而且小於等於 60 的行 [root@hai7 ~] $awk -F: ' $3 >= 50 && $3 <= 60 {print NR, $1} ' /etc/passwd 31 tss 2 :篩選第 3 個字段等於 0 或大於等於 1000 的行 [root@hai7 ~] $awk -F: ' $3 == 0 || $3 >= 1000 {print NR, $1} ' /etc/passwd 1 root 29 nfsnobody 43 dong 3 :篩選第 3 個字段小於等於 1000 之外的行 $awk -F: '!( $3 <= 1000 ) {print NR, $1} ' /etc/passwd 29 nfsnobody
先定義條件第
3 字段大於等於
1000 ,若是成立則打印
type ="user" ,不成立打印
type ="sys"
[root@hai7 ~]$awk -F: '{$
3 >=
1000 ?
type ="user" :
type ="sys" ;printf
"%+15s %s\n" ,$
1 ,
type }' /etc /passwd
root sys
nfsnobody user
6 awk-PATTERN
若是未指定:空模式,匹配每一行
/regular expression/:僅處理可以模式匹配到的行,須要用/ /括起來
例1:判斷磁盤利用率,取出設備行
$df|awk -F " +|%" '/^\/dev\/sd/{print $1,$5}'
/dev/sda2 11
/dev/sda3 1
/dev/sda1 16
例2:統計磁盤文件系統類型
$awk -F" +" '/^UUID/{print $3}' /etc/fstab|sort|uniq -c
2 swap
3 xfs
relational expression: 關係表達式,結果爲「真」纔會被處理
真:結果爲非0值,非空字符串
假:結果爲空字符串或0值
示例
空格或者非0數值,返回值爲非空,結果都爲真,能夠打印結果 awk -F: '" "{print $1}' /etc/passwd
awk -F: '1{print $1}' /etc/passwd
awk ‘!0’ /etc/passwd
空值或者0,返回值爲空,結果爲假,不作處理 awk -F: ' ""{print $1} ' /etc/passwd
awk -F: '0{print $1}' /etc/passwd
awk ‘!12345’ /etc/passwd
任何非0值取反都爲空
下例分爲兩條命令
[root@hai7 ~]$awk -F: 'i=1;j=1{print i,j}' /etc/passwd
named:x:25:25:Named:/var/named:/sbin/nologin
1 1
i=1;j=1{print i,j}是兩條命令
i=1省略了{print ...}因此默認打印$0
seq 10 |awk ‘i=0’
取偶數行或奇數行 打印奇數行,由於i沒有指定值因此爲空,第一次執行時爲空=!空,因此打印1,第二次執行時,非空=!非空值爲0,因此不處理,以此類推,能夠經過seq 10 | awk '{i=!i;print i}'
查看返回結果
seq 10 |awk 'i=1'
打印全部數字
seq 10 | awk 'i=!i'
打印奇數行
seq 10 | awk '!(i=!i)'
打印偶數行
seq 10 |awk -v i=1 'i=!i'
打印偶數行
line ranges:行範圍
利用正則表達式寫法取範圍 startline,endline:/pat1/,/pat2/ 不支持直接給出數字格式 awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd
先要處理指定的行範圍,能夠利用NR記錄編號來實現 awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
BEGIN/END模式 BEGIN{}: 僅在開始處理文件中的文本以前執行一次 END{}:僅在文本處理完成以後執行一次
1
2
3
4
5
6
7
8
9
10
11
12
13
示例1:
[root@hai7 ~]$awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd
USER USERID <==BEGIN的內容
root:0
apache:48
named:25
end file <==END的內容
示例2:
$awk -F: '{print "USER USERID";print $1":"$3} END{print "end file"}' /etc/passwd
USER USERI <==不是開始處理的文本,會被循環打印
root:0
USER USERI
bin:1
7. awk action
7.1awk控制語句if-else
語法 if(condition){statement;…}[else statement] if(condition1){statement1}else if(condition2){statement2}else{statement3}
使用場景:對awk取得的整行或某個字段作條件判斷
示例:
示例1:取出第3字段大於等於1000的行
awk -F:
'{if($3 >=1000)print $1 ,$3 }' /etc/passwd
awk -F:
'$3 >=1000{print $1 ,$3 }' /etc/passwd
效果相同,格式不一樣控制語句是action裏的要寫在花括號內,判斷語句是屬於patter的要寫在花括號外面
示例2:取磁盤利用率高於5%的
$df|awk -F
" +|%" '/^\/dev\/sd/{
if ($
5 >
5 ){print $
1 ,$
5 ;print
"it is full" }}'
/dev/sda2
11
it is full
/dev/sda1
16
it is full
示例3:取訪問日誌中IP地址重複次數超過100的,放到防火牆中
[root
@hai7 ~]
$ab -c1
0 -n
100 http:
// 172.20 .
50.201 / 實驗準備屢次訪問某地址
[root
@hai7 ~]
$cat /var/
log /httpd/access_log|awk -F
" " '{print $1}' |uniq -c|awk -F
" " '{if($1>100){print $2}' |
while read ip;
do iptables -A INPUT -
s $ip -j REJECT;done
[root
@hai7 ~]
$iptables -F 清空防火牆
示例3:shell類型使用bash的行
awk -F:
'{if($NF =="/bin/bash") print $1 }' /etc/passwd
示例4:第3字段大於等於1000的標記爲Common user,不然標記爲root or Sysuser
awk -F: '{if(
$3 >=1000) {printf
"Common user: %s\n" ,
$1 } else {printf
"root or Sysuser: %s\n" ,
$1 }}' /etc/passwd
awk -F: '{if(
$3 >=1000) printf
"Common user: %s\n" ,
$1 ; else printf
"root or Sysuser: %s\n" ,
$1 }' /etc/passwd
7.2 awk控制語句 while循環
語法: while(condition){statement;…}
條件「真」,進入循環;條件「假」,退出循環
使用場景: 對一行內的多個字段逐一相似處理時使用 對數組中的各元素逐一處理時使用
示例:
示例1:用awk寫1..100相加
$awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}'
5050
示例2:找出無論前面多少空格linux16開頭的行,統計各字段字符串長度
[root
@hai7 ~]awk
'/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg
示例中
length 是系統函數,用來統計括號中字符串長
[root
@hai7 ~]
$awk 'BEGIN{print length("sdgdgasdfwergejut")}'
17
示例3:統計字段字符串長度超過10的
awk '/^[[:
space :]]*linux16/{i=
1 ;
while (i<=NF) {
if (
length ($i)>=
10 ) {print $i,
length ($i)}; i++}}' /etc/grub2.cfg
示例4:判斷隨機數最大值與最小值
1 :生成以逗號爲分隔符的隨機數到文件f1
[root@hai7 ~] $(echo
"$RANDOM" ;
for ((i=
1 ;i<
100 ;i++));
do echo -n
",$RANDOM" ;done)>f1
2 : 取出隨機數最大值和最小值
[root@hai7 ~] $awk -
F' ,
' ' {max=$
1 ;
min =$
1 ;i=
2 ;while(i<=NF){
if ($i>max){max=$i}
else if ($i<
min ){
min =$i};i++;}}END{print
"max=" max,
"min=" min }
' f1 max=32377 min=148 3:判斷結果是否正確 [root@hai7 ~]tr ' ,
' ' \
n' <
f1. txt|shot -nr
7.3 控制語句 do-while循環
語法 do {statement;…}while(condition)
意義 不管真假,至少執行一次循環體
示例:
示例1:1..100相加
$awk 'BEGIN{sum=
0 ;i=
1 ;
do {sum+=i;i++}
while (i<=
100 );print sum}
示例2:統計linux16行,大於10個字符的字段
$awk '/^[[:space:]]*linux16/{i=
1 ;
do {
if (
length ($i)>=
10 ){print $i,
length ($i)}; i++}
while (i<=NF)}' /etc/grub2.cfg
7.4 awk控制語句 for循環
語法 for(expr1;expr2;expr3) {statement;…}
常見用法: for(variable assignment;condition;iteration process){for-body}
特殊用法:可以遍歷數組中的元素 - 語法:for(var in array) {for-body}
示例:
示例1:統計linux16行,各字段字符長度,
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i ,length($i )}}' /etc/grub2.cfg
示例2:從1+到100相加
awk
'BEGIN{sum=0;for(i=1;i<=100;i++)sum+=i;print sum}'
7.5 awk控制語句 switch語句
語法: swich定義的表達式,是否爲case後的只或者正則表達式,若是是則執行statement1, 若是不匹配則繼續判斷第二個case後的值是否匹配,匹配則執行statement2,都不匹配則執行default後續。
格式 switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; …; default: statementn}
7.6 awk控制語句 break、continue及next
[root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)break;sum+=i} ;print sum}'
1225
循環到50,就不日後加了
continue [n]結束單次循環
1 :i
%2 ==
1 意思爲奇數循環,跳過奇數循環,得偶數總和
[root
@hai7 /etc/selinux]
$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i} ;print sum}'
2550
2 :結束第
50 次循環,會繼續進行後續循環
[root
@hai7 /etc/selinux]
$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)continue;sum+=i} ;print sum}'
5000
next: 提早結束對本行處理而直接進入下一行處理(awk自身循環)
打印 奇數行 awk -F: '{if( $3 % 2 != 0 )next;print NR, $1 , $3} ' /etc/passwd
8. 性能比較
使用awk、shell、bc計算100000相加,參考所用時間,判斷工做性能 一、awk for循環
[root
@hai7 /etc/selinux]
$time awk
'BEGIN{sum=0;for(i=1;i<=100000;i++)sum+=i ;print sum}'
5000050000
real 0m
0 .
011 s
user 0m
0 .
010 s
sys 0m
0 .
001 s
二、awk while循環
2. $
time awk 'BEGIN{sum=
0 ;i=
1 ;
while (i<=
100 ){sum+=i;i++};print sum}'
5050
real 0 m0
.003 s
user
0 m0
.002 s
sys
0 m0
.001 s
三、shell for循環
$time for ((sum=
0 ,i=
1 ;i<=
100000 ;i++));
do let sum+=i;
done ;
echo $sum
real
0 m0.
666 s
user
0 m0.
666 s
sys
0 m0.
000 s
四、shell while循環
$time ( sum=
0 ;i=
1 ;
while [
$i -le
100000 ] ;
do let sum+=i;
let i++;
done ;
echo $sum )
5000050000
real
0 m1.
064 s
user
0 m0.
992 s
sys
0 m0.
072 s
五、bc計算
$time seq
-s +
100000 |bc
5000050000
real
0 m0.
041 s
user
0 m0.
036 s
sys
0 m0.
007 s
9. awk數組
9.1 awk支持關聯數組
arr[「key」]=value 鍵值對,每一個鍵後面對應着相應的值, 當按下相應的鍵時, 就會輸出相應的結果
格式 array[index-expression]
index-expression:
可以使用任意字符串;字符串要使用雙引號括起來
若是某數組元素事先不存在,在引用時,awk會自動建立此元素,並將其值初始化爲「空串」
若要遍歷數組中的每一個元素,要使用for循環,格式爲for(var in array) {for-body}
示例
•awk ‘!arr[0 ] + + ′ d u p f i l e 去 掉 重 復 行 , 例 如 文 件 內 容 爲 0]++′dupfile去掉重複行,例如文件內容爲 cat f2 abc cvb abc 當awk讀入第一行時,arr的下標爲abc,沒有賦值爲空,取反爲非空,因此打印第一行,arr[abc]=1 讀入第二行是,arr的下標爲cbv,沒有賦值爲空,取反爲非空,因此打印 讀入第三行時,arr的下標爲abc,值爲1,取反爲空,因此不打印 arr[abc]=2
去掉重複行還可使用sort -u f2 •awk ‘{!arr[0 ] + + ; p r i n t 0]++;print 0, arr[$0]}’ dupfile
分別定義數組weekdays的鍵值對爲[「mon」]=」Monday」,[「tue」]=」Tuesday」,經過for來遍歷
awk 'BEGIN{weekdays[
"mon" ]=
"Monday" ;weekdays[
"tue" ]=
"Tuesday" ;
for (i
in weekdays) {print weekdays[i]}}'
統計tcp狀態,NF表明最後一個字段,i表示值,state[i]表示累計結果
netstat -
tan | awk '/^tcp/{state[$NF]++}END{
for (i
in state) { print i,state[i]}}'
統計IP訪問次數,f1爲導出的IP訪問日誌格式爲,默認以空格爲分隔符 172.20.7.53 - - [10/Sep/2018:10:18:53 +0800] 「GET / HTTP/1.0」 403 4961 「-」 「ApacheBench/2.3」
awk '{ip[$1]++}
END {for (i in ip){print ip[i],i}}' f1|sort -rn
分別統計男生女生的平
[root
@hai7 /data]$cat f2
name grade boyorgirls
A
76 G
B
98 M
C
66 M
D
95 G
E
86 G
F
79 M
[root
@hai7 /data]$awk '!/ ^name/{
if ($
3 ==
"M" ){score_m+=$
2 ;number_m++}
else {score_g+=$
2 ;number_g++}}END{
print "avg_m=" score_m/number_m
"" ,
"avg_g=" score_g/number_g}
' f2 avg_m=81 avg_g=85.6667
方法二
[root
@hai7 /data]
$awk 'NR!=1{score[$3]+=$2;num[$3]++}END{for(sex in num){print sex":avg="score[sex]/num[sex]}}' f2
G :avg= 85.6667
M :avg= 81
9.2 自定義函數
格式: function name ( parameter, parameter, … ) { statements return expression }
示例:
cat fun.awk
function max (v1,v2) {
v1>v2?
var =v1:
var =v2
return var
}
BEGIN{a=
3 ;b=
2 ;
print max(a,b)}
awk –f fun.awk
3
9.3 awk中調用shell命令
空格是awk中的字符串鏈接符,若是system中須要使用awk中的變量可使用空格分隔,或者說除了awk的變量外其餘一概用」「引用起來。
格式 system(「$var」)
示例 awk BEGIN'{system("hostname") }'
awk 'BEGIN{score=100; system("echo your score is " score) }'
9.4 awk腳本
將awk程序寫成腳本,直接調用或執行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1 :將pattern{action statements;..}寫到文本中
[root
@hai7 /data]
$cat f3
{
if (
$3 >=
1000 )
print $1 ,
$3 }
2 :調用文原本篩選文件
$awk -F: -f f3 /etc/passwd
nfsnobody
65534
v9
1000
3 :創建awk執行腳本
$cat f3
{
if (
$3 >=
1000 )
print $1 ,
$3 } <==pattern{action statements;..}
4 :加執行權限
chmod +
x f3
5 :調用腳原本過濾文本
./f3 –F:
/etc/passwd
9.4.1 向awk腳本傳遞參數
格式 awkfile var=value var2=value2… Inputfile
注意事項
在BEGIN過程當中不可用。直到首行輸入完成之後,變量纔可用。
能夠經過-v 參數,讓awk在執行BEGIN以前獲得變量的值。命令行中每個指定的變量都須要一個-v參數
示例
1 :編輯awk腳本
cat test.awk
#!/bin/awk –f
{
if (
$3 >=
min &&
$3 <=
max )
print $1 ,
$3 }
2 :加執行權限
chmod +x test.awk
3 :執行腳本,向腳本傳遞變量以下,也可使用-v
min =
100 ,每一個變量前都要加-v
./test.awk -F:
min =
100 max =
200 /etc/passwd
10. awk數值處理
用:作分隔符將
2008 :
08 :
08 08 :
009 :
09 分割爲
5 段,分別存放在下標爲
1 的
str [
1 ]=
2008 ,
str [
2 ]=
08 ...
echo
"2008:08:08 08:009:09" |awk
'{split($0,str,":")}END{for(i in str)print i,str[i]}'
4 009
5 09
1 2008
2 08
3 08 08
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7f770a53f2.css" rel="stylesheet">
</div>