awk用法和詳細實例


00x01 awk介紹

   

awk: Aho, Weinberger, Kernighan,報告生成器,格式化文本輸出,用於在linux/unix下對文本和數據進行處理。數據可以來自標準輸入、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能

有多種版本: New awk(nawk), GNU awk(gawk)

   gawk:模式掃描和處理語言


00x02 awk基本用法


基本用法

awk [options] ‘program’ var=value file…

awk [options] -f programfile var=value file…

awk [options] 'BEGIN{ action;… } pattern{ action;… } END{action;… }' file ...

awk 程序通常由: BEGIN語句塊、能夠使用模式匹配的通用語句塊、 END語句塊,共3部分組成

program通常是被單引號或雙引號中

   選項:

    -F 指明輸入時用到的字段分隔符

    -v var=value: 自定義變量

基本格式:

awk [options] 'program' file…

  program:pattern{action statements;..}

  pattern和action:

pattern部分決定動作語句何時觸發及觸發事件

BEGIN,END

action statements對數據進行處理,放在{}內指明

print, printf

分割符、域和記錄

awk執行時, 由分隔符分隔的字段(域)標記$1,$2..$n稱爲域標識。 $0爲所有域,注意:和shell中變量$符含義不同

文件的每一行稱爲記錄

省略action,則默認執行 print $0 的操作


00x03 awk工作原理


第一步:執行BEGIN{action;… }語句塊中的語句

第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這個過程,直到文件全部被讀取完畢。

第三步:當讀至輸入流末尾時,執行END{action;…}語句塊

BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中

END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如打印所有行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊

pattern語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取到的行, awk讀取的每一行都會執行該語句塊


00x04 print


print格式: print item1, item2, ...

  要點:

(1) 逗號分隔符

(2) 輸出的各item可以字符串,也可以是數值;當前記錄的字段、

變量或awk的表達式

(3) 如省略item,相當於print $0

  示例:

awk '{print "hello,awk"}'

awk –F: '{print}' /etc/passwd

awk –F: ‘{print “wang”}’ /etc/passwd

awk –F: ‘{print $1}’ /etc/passwd

awk –F: ‘{print $0}’ /etc/passwd

awk –F: ‘{print $1”\t”$3}’ /etc/passwd

tail –3 /etc/fstab |awk ‘{print $2,$4}’


00x05 變量


變量:常用內置變量

wKioL1nAc6eBhCJ8AABhvsLP9Ts284.png

 a、FS

 FS field-separator  輸入字段分隔符,默認爲空白字符

   使用FS的好處就是可以在內部調用這個變量

[root@localhost tmp]# awk -v FS=":" '{print $1,FS,$3}' passwd
root : 0
bin : 1
daemon : 2
adm : 3
lp : 4
sync : 5

[root@localhost tmp]# awk -F ":" '{print $1":"$3}' passwd
root:0
bin:1
daemon:2
adm:3
lp:4
sync:5

b、OFS

   output field-separator  輸出字段分隔符,默認爲空白字符

[root@localhost tmp]# awk -v FS=":" -v OFS="$" '{print $1,$3,$7}' passwd
root$0$/bin/bash
bin$1$/sbin/nologin
daemon$2$/sbin/nologin
adm$3$/sbin/nologin


c、RS

    輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效

 

[root@localhost tmp]# awk -v FS=":" -v OFS="$" '{print $1,$3,$7}' passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-bus-proxy:x:999:997:systemd
Bus
Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd
Network

[root@localhost tmp]# cat test
list a b dd
list2 a2 b2 dd2
list4 a3 b3 dd3
[root@localhost tmp]# cat test |awk -v RS=" " -v OFS="++" '{print $1,$2}'
list++              
a++
b++  
dd++list2               #指定 RS“ ”,dd\nlist2,FS默認爲空白字符,$1就是dd
a2++
b2++
dd2++list4
a3++                                         
b3++
dd3++

d、 ORS

   輸出記錄分隔符,輸出時用指定符號代替換行符

[root@localhost tmp]# awk -v RS=" " -v ORS="%" '{print}' passwd
root:x:0:0:yemo,62985600:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
systemd-bus-proxy:x:999:997:systemd%Bus%Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd%Network%Management:/:/sbin/nologin
dbus:x:81:81:System%message%bus:/:/sbin/nologin
polkitd:x:998:996:User%for%polkitd:/:/sbin/nologin
tss:x:59:59:Account%used%by%the%trousers%package%to%sandbox%the%tcsd%daemon:/dev/null:/sbin/nologin

e、 NF

   字段數量

[root@localhost tmp]# cat passwd |awk -F: '{print NF}'   #不需要使用$
7
7
7
7


可以用於循環每行每個字段

[root@localhost tmp]# cat passwd |awk -F: '{for(i=0;i<NF;i++){print $i}}'
root:x:0:0:yemo,62985600:/root:/bin/bash
root
x
0
0
yemo,62985600
/root
bin:x:1:1:bin:/bin:/sbin/nologin


f、 NR

  行號

[root@localhost tmp]# cat passwd |awk -F: '{print NR}'
1
2
3
4
[root@localhost tmp]# awk 'END{print NR}' passwd
22


e、 FNR

  各文件分別計數,行號

[root@localhost tmp]# awk '{print FNR}' /etc/fstab /etc/inittab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
...


f、 FILENAME

     當前文件名

[root@localhost tmp]# awk '{print FILENAME}' /etc/fstab
/etc/fstab
/etc/fstab
/etc/fstab
/etc/fstab
/etc/fstab
/etc/fstab


g、 ARGC 

    命令行參數的個數

[root@localhost tmp]# awk 'END{print ARGC}' /etc/fstab /etc/inittab
3


h、 ARGV

     數組,保存的是命令行所給定的各參數

[root@localhost tmp]# awk 'END{print ARGV[1]}' /etc/fstab /etc/inittab
/etc/fstab
[root@localhost tmp]# awk 'END{print ARGV[0]}' /etc/fstab /etc/inittab
awk
[root@localhost tmp]# awk 'END{print ARGV[2]}' /etc/fstab /etc/inittab
/etc/inittab


00x06 自定義變量和環境變量

   自定義變量(區分字符大小寫)

(1) -v var=value

(2) 在program中直接定義

[root@localhost tmp]# awk -v a="sh" 'BEGIN{print a}'
sh


[root@localhost tmp]# cat awkscript
{print script,$1,$2}
[root@localhost tmp]# awk -F: -f awkscript script="awk" /etc/passwd
awk root x                         #引用文件的變量,相當於已經定義,不用再-v聲明
awk bin x
awk daemon x
awk adm x
awk lp x
awk sync x
awk shutdown x
awk halt x


環境變量:


wKiom1nAdTuTpqEnAADk4UZQEdw277.png


00x07 printf格式化輸出


wKioL1nAdUvDmfbrAACrw3Of28w014.png




a、格式printf “FORMAT” , item1, item2, ...

          (1) 必須指定FORMAT

(2) 不會自動換行,需要顯式給出換行控制符, \n

(3) FORMAT中需要分別爲後面每個item指定格式符

  b、實例

printf '\n'$(tput setaf 2; tput setab 0; tput bold)'background color show'$(tput sgr0)'\n\n'

 wKioL1nAdZng2jhBAAAESs6kKQs413.png

 %s字符串,\t打印tab,\n回車,printf默認不會輸出換行符

[root@localhost matrix]# echo "hello world"|awk '{printf "%s\t%s\n",$1,$2}'
hello    world


 %d十進制

[root@localhost matrix]# echo "12580 124"|awk '{printf "%d\t%d\n",$1,$2}'
12580    124


%o無符號八進制

[root@localhost matrix]# echo "12580 124"|awk '{printf "%o\t%o\n",$1,$2}'
30444    174


%x十六進制

[root@localhost matrix]# echo "12580 124"|awk '{printf "%x\t%x\n",$1,$2}'
3124    7c


[root@localhost matrix]# awk -F: '{printf "Username: %s,UID:%d\n",$1,$3}' /tmp/passwd
Username: root,UID:0
Username: bin,UID:1
Username: daemon,UID:2
Username: adm,UID:3
Username: lp,UID:4


00x08 操作符


算術操作符:

      x+y, x-y, x*y, x/y, x^y, x%y

     -x: 轉換爲負數

     +x: 轉換爲數值

[root@localhost matrix]# awk 'BEGIN{print 2-4}'
-2
[root@localhost matrix]# awk 'BEGIN{print 2^3}'
8
[root@localhost matrix]# awk -v a=m 'BEGIN{print +a}'
0
[root@localhost matrix]# awk -v a=m 'BEGIN{print a}'
m
[root@localhost matrix]# awk -v a=5 'BEGIN{print -a}'
-5


字符串拼接

[root@localhost matrix]# awk -v a="hello" -v b="Rie Kugimiya" 'BEGIN{print ab}'
[root@localhost matrix]# awk -v a="hello" -v b="Rie Kugimiya" 'BEGIN{print a b}'
helloRie Kugimiya


賦值操作符: =, +=, -=, *=, /=, %=, ^=,++, --

[root@localhost matrix]# awk  'BEGIN{b=10;print b}'
10
[root@localhost matrix]# awk -F: '{for(i=0;i<NF;i++){print i}}' /tmp/passwd
0
1
2
3
4
5
6
0
1
2
3
4
5
6


比較操作  ==, !=, >, >=, <, <=

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($3>100){print $0}}'
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
yemo:x:1000:1000::/home/yemo:/bin/bash


模式匹配  ~:左邊是否和右邊匹配包含

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($1 ~/.*oo.*/){print}}'
root:x:0:0:yemo,62985600:/root:/bin/bash
[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 ~/.*oo.*/){print}}'
root:x:0:0:yemo,62985600:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin


!~:是否不匹配

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 !~/.*oo.*/){print}}'
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin


邏輯操作符  與&&,或||,非!

[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 !~/.*oo.*/ &&$3 >100 ){print}}'
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
yemo:x:1000:1000::/home/yemo:/bin/bash
[root@localhost matrix]# awk -F: '!($3>=500) {print $3}' /etc/passwd
0
1
2
3
4
5
6


函數調用

    自定義函數調用

[root@localhost matrix]# echo "11 22"|awk '{print "max=",max($1,$2)}function max(a,b){if(a>b){return a;}else{return b;}}'
max= 22


     內部函數調用

[root@localhost matrix]# echo "ad 12 22 dd"|awk 'split($0,a){for(i in a)printf a[i]}'
ddad1222


條件表達式

               三元表達式: selector?if-true-expression:if-false-expression

[root@localhost matrix]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
           root:Sysadmin or SysUser
            bin:Sysadmin or SysUser
         daemon:Sysadmin or SysUser
            adm:Sysadmin or SysUser
             lp:Sysadmin or SysUser
           sync:Sysadmin or SysUser
       shutdown:Sysadmin or SysUser
           halt:Sysadmin or SysUser
           mail:Sysadmin or SysUser
       operator:Sysadmin or SysUser
          games:Sysadmin or SysUser
            ftp:Sysadmin or SysUser
         nobody:Sysadmin or SysUser
systemd-bus-proxy:Sysadmin or SysUser
systemd-network:Sysadmin or SysUser
           dbus:Sysadmin or SysUser
        polkitd:Sysadmin or SysUser
            tss:Sysadmin or SysUser
           abrt:Sysadmin or SysUser
        postfix:Sysadmin or SysUser
           sshd:Sysadmin or SysUser
           yemo:Common User


[root@localhost matrix]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%-15s:%-s\n",$1,usertype}' /etc/passwd
root           :Sysadmin or SysUser
bin            :Sysadmin or SysUser
daemon         :Sysadmin or SysUser
adm            :Sysadmin or SysUser
lp             :Sysadmin or SysUser
sync           :Sysadmin or SysUser
shutdown       :Sysadmin or SysUser
halt           :Sysadmin or SysUser
mail           :Sysadmin or SysUser


00x09  PATTERN:根據pattern條件,過濾匹配的行,再做處理


(1)如果未指定:空模式,匹配每一行

[root@localhost tmp]# awk '{print $1}' test
list
list2
list4


(2) /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來

[root@localhost tmp]# cat passwd |awk -F: '/^root\>/ {print }'
root:x:0:0:yemo,62985600:/root:/bin/bash                #支持位置鉚釘和單詞鉚釘
[root@localhost tmp]# cat passwd |awk -F: '/root/ {print }'   #包含root的全都匹配
root:x:0:0:yemo,62985600:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin


(3) relational expression: 關係表達式,結果爲“真”纔會被處理

真:結果爲非0值,非空字符串

     假:結果爲空字符串或0值

[root@localhost tmp]# cat passwd |awk -F: 'i=1;j=1{print i,j}'      #i=1後默認有{print $0}
root:x:0:0:yemo,62985600:/root:/bin/bash
1 1
bin:x:1:1:bin:/bin:/sbin/nologin
1 1
daemon:x:2:2:daemon:/sbin:/sbin/nologin
1 1


[root@localhost tmp]# cat passwd |awk -F: '$3>500  {print }'
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
yemo:x:1000:1000::/home/yemo:/bin/bash


匹配finger空的行

[root@localhost tmp]# cat passwd |awk -F: '!$5  {print }'
abrt:x:173:173::/etc/abrt:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
yemo:x:1000:1000::/home/yemo:/bin/bash


  匹配默認bash是/bin/bash的用戶

[root@localhost tmp]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' passwd
root /bin/bash
yemo /bin/bash


  匹配 bash結尾

[root@localhost tmp]# awk -F: '$NF ~/bash$/{print $1,$NF}' passwd
root /bin/bash
yemo /bin/bash


(4) line ranges: 行範圍

             startline,endline: /pat1/,/pat2/ 不支持直接給出數字格式

[root@localhost tmp]# awk -F: '/^root\>/,/^mail\>/{print $1,$3}' passwd
root 0                                                       #類似sed的用法
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8


[root@localhost tmp]# awk -F: '(NR>=3&&NR<=10){print $1,$3}' passwd
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11


  (5) BEGIN/END模式

                BEGIN{}: 僅在開始處理文件中的文本之前執行一次

                END{}:僅在文本處理完成之後執行一次

[root@localhost tmp]# seq 10|awk ''
[root@localhost tmp]# seq 10|awk '1'
1
2
3
4
5
6
7
8
9
10
[root@localhost tmp]# seq 10|awk '{i=!i;print i}'
1
0
1
0
1
0
1
0
1
0
[root@localhost tmp]# seq 10|awk '{i=!i}'
[root@localhost tmp]# seq 10|awk 'i=0;i=!i'
1
2
3
4
5
6
7
8
9
10
[root@localhost tmp]# seq 10|awk 'i=1;i=!i'
1
2
3
4
5
6
7
8
9
10
[root@localhost tmp]# seq 10|awk -v i=1 'i=!i'
2
4
6
8
10
[root@localhost tmp]# seq 10|awk '!(i=!i)'
2
4
6
8
10


00x0a action


wKiom1nAeDuRMDkzAAA2ROnR7aM858.png


00x0b 控制語句



wKiom1nAeJaSBsCxAABfo5u7e70596.png


 1)if循環

       if(condition){statement;…}[else statement]

[root@localhost tmp]# cat passwd |awk -F: '{if($3>500){print}}'
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
yemo:x:1000:1000::/home/yemo:/bin/bash


[root@localhost tmp]# cat passwd |awk -F: '{if($NF=="/bin/bash"){print}}'
root:x:0:0:yemo,62985600:/root:/bin/bash
yemo:x:1000:1000::/home/yemo:/bin/bash


[root@localhost tmp]# cat passwd |awk -F: '{if($5!=""){print}}'
root:x:0:0:yemo,62985600:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost tmp]# cat passwd |awk -F: '{if($3>500){printf "commusr:%s\n",$1}else{printf "sysuser:%s\n",$1 }}'
sysuser:root
sysuser:bin
sysuser:daemon
sysuser:adm
sysuser:games
sysuser:ftp
sysuser:nobody
commusr:systemd-bus-proxy
sysuser:systemd-network
sysuser:dbus
commusr:polkitd
sysuser:tss
sysuser:abrt
sysuser:postfix
sysuser:sshd
commusr:yemo


[root@localhost tmp]# df -P|awk -F "% " '/dev\/sd/ {print}'|awk '{if($5>3)printf "%s\t%s\n",$1,$5}'
/dev/sda2    4%
/dev/sda1    3%


      if(condition1){statement1}else if(condition2){statement2}else{statement3}

[root@localhost tmp]# echo "10 99 100 60 50"|awk '{for(i=1;i<(NF+1);i++) {if($i>=90){print $i,"verygood";}else if($i>=60&&$i<90){print $i,"is ok";}else {print $i"you are too low"} }}'
10you are too low
99 verygood
100 verygood
60 is ok
50you are too low


      while循環

語法: while(condition){statement;…}

 條件“真”,進入循環;條件“假”, 退出循環

 使用場景:

對一行內的多個字段逐一類似處理時使用

對數組中的各元素逐一處理時使用

[root@localhost tmp]# awk '/^\s*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
net.ifnames=0 13


[root@localhost tmp]# awk '/^\s*linux16/{i=1;while(i<=NF){if(length($i)>10){print $i,length($i)};i++ } }' /etc/grub2.cfg
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46
crashkernel=auto 16
LANG=en_US.UTF-8 16
net.ifnames=0 13
/vmlinuz-0-rescue-8665dcc4833c41eaa11fa716f7dcd792 50
root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46
crashkernel=auto 16


do-while循環

語法: do {statement;…}while(condition)

意義:無論真假,至少執行一次循環體

[root@localhost tmp]# awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}'
5050
[root@localhost tmp]# awk 'BEGIN{total=1;i=1;do{total+=i;i++;}while(i<=0);print total}'
2
[root@localhost tmp]# awk 'BEGIN{i=0;print ++i,i}'          #先加後賦值
1 1
[root@localhost tmp]# awk 'BEGIN{i=0;print i++,i}'          #先賦值在加
0 1

  for循環

     語法:for(expr1;expr2;expr3) {statement;…}

常見用法:

          for(variable assignment;condition;iteration process){for-body}

特殊用法:能夠遍歷數組中的元素

echo "10 99 100 60 50"|awk '{for(i=1;i<(NF+1);i++) {if($i>=90){print $i,"verygood";}else if($i>=60&&$i<90){print $i,"is ok";}else {print $i"you are too low"} }}'
10you are too low
99 verygood
100 verygood
60 is ok
50you are too low


[root@localhost tmp]# cat access.log |awk '{++arr[$1]}{for(i in arr){print i,arr[i]}}'
192.168.1.44 34
172.16.100.76 204
192.168.1.100 12
192.168.1.101 1
192.168.1.110 83
192.168.99.72 18
172.16.100.125 18
127.0.0.1 7
192.168.1.121 13
192.168.1.112 27
172.16.0.100 4
172.16.100.126 3
192.168.1.113 583
172.16.23.100 14
192.168.1.114 12
192.168.6.1 42
172.16.250.227 68
192.168.1.106 22
172.16.233.133 112
192.168.1.107 68
192.168.1.108 3

switch語句

      語法: switch(expression) {case VALUE1 or /REGEXP/:statement1; case VALUE2 or /REGEXP2/: statement2;...; default: statementn}

           break和continue

         

[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<=100;i++){if(i%2==0)continue;sum+=i}print sum  }'
2500

 

[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<=100;i++){if(i==55)break;sum+=i}print sum  }'
1485
[root@localhost ~]# awk -F: '{if($3%2!=0)next;print $1,$3}' /tmp/passwd
root 0
daemon 2
lp 4
shutdown 6
mail 8
games 12
ftp 14
systemd-network 192
polkitd 998
sshd 74
yemo 1000


   00x0b  awk數組

     a)  關聯數組: array[index-expression]

     index-expression:

(1) 可使用任意字符串;字符串要使用雙引號括起來

(2) 如果某數組元素事先不存在,在引用時, awk會自動創建此元素,並將其值初始化爲“空串”

若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷

     若要遍歷數組中的每個元素,要使用for循環

  for(var in array) {for-body}

  注意: var會遍歷array的每個索引

[root@localhost tmp]# cat access.log |awk '{++arr[$1]}{for(i in arr){print i,arr[i]}}'
192.168.1.44 34
172.16.100.76 204
192.168.1.100 12
192.168.1.101 1
192.168.1.110 83
192.168.99.72 18
172.16.100.125 18
127.0.0.1 7
192.168.1.121 13
192.168.1.112 27
172.16.0.100 4
172.16.100.126 3
192.168.1.113 583
172.16.23.100 14
192.168.1.114 12
192.168.6.1 42
172.16.250.227 68
192.168.1.106 22
172.16.233.133 112
192.168.1.107 68
192.168.1.108 3

 使用關聯數組對重複IP地址計數,以IP地址爲索引,出現相同索引的就自加,達到計數的目的,數組缺省值爲0。


00x0c 函數


     a)內置函數

          

wKiom1nAefnyepDxAAC3uxLNQK0997.png


 01  sub函數匹配記錄中最大、最靠左邊的子字符串的正則表達式,並用替換字符串替換這些字符串。如果沒有指定目標字符串就默認使用整個記錄。替換隻發生在第一次匹配的時候。

               sub (regular expression, substitution string):

                sub (regular expression, substitution string, target string)

[root@localhost tmp]# awk '{sub(/a/,"test");print}' test
listtest a ba dad
listtest2 a2 ba2 dad2
listtest4 a3 ba3 dad3
[root@localhost tmp]# cat test
lista a ba dad
lista2 a2 ba2 dad2
lista4 a3 ba3 dad3

02   gsub函數作用如sub,但它在整個文檔中進行匹配。

[root@localhost tmp]# awk '{gsub(/a/,"test");print}' test
listtest test btest dtestd
listtest2 test2 btest2 dtestd2
listtest4 test3 btest3 dtestd3


03   index  函數返回子字符串第一次被匹配的位置,偏移量從位置1開始。

                  index(string, substring)


04  substr函數返回從位置1開始的子字符串,如果指定長度超過實際長度,就返回整個字符串。

                substr( string, starting position )

                 substr( string, starting position, length of string )


05   split函數可按給定的分隔符把字符串分割爲一個數組。如果分隔符沒提供,則按當前FS值進行分割。

              split( string, array, field separator )

               split( string, array )


06  length函數返回記錄的字符數。

               length( string )

                length


07 match函數返回在字符串中正則表達式位置的索引,如果找不到指定的正則表達式則返回0。match函數會設置內建變量RSTART爲字符串中子字符串的開始位置,RLENGTH爲到子字符串末尾的字符個數。substr可利於這些變量來截取字符串。

                 match( string, regular expression )


08  toupper和tolower函數可用於字符串大小間的轉換,該功能只在gawk中有效。

                     toupper( string )

                     tolower( string )



  b) 數學函數 

wKiom1nAepGDMuhCAABXo0geFgY629.png

00x0d 通過system調用系統命令

           空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk的變量外其他一律用""引用起來。

[root@localhost ~]# awk 'BEGIN{system("hostname")}'
localhost.localdomain
[root@localhost ~]# awk 'BEGIN{s=100;system("echo your score is" s)}'
your score is100
[root@localhost ~]# awk 'BEGIN{s=100;system("echo your score is " s)}'
your score is 100


00x0e 創建awk腳本

[root@localhost tmp]# vim tstawk.awk
[root@localhost tmp]# cat tstawk.awk
#!/bin/awk -f
{if($3>=1000)print $1,$3}
[root@localhost tmp]# awk -F: -f tstawk.awk passwd
yemo 1000
[root@localhost tmp]# chmod +x tst2.awk
[root@localhost tmp]# cat tst2.awk
#!/bin/awk -f
{if($3>=1000)print $1,$3}
[root@localhost tmp]# ./tst2.awk  -F: passwd
yemo 1000


向awk腳本傳遞參數

           格式:

                    awkfile var=value var2=value2... Inputfile

     注意:在BEGIN過程中不可用。直到首行輸入完成以後,變量纔可用。可以通過-v 參數,讓awk在執行BEGIN之前得到變量的值。命令行中每一個指定的變量都需要一個-v參數

[root@localhost tmp]# cat tst2.awk
#!/bin/awk -f
{if($3>=min && $3<=max)print $1,$3}
[root@localhost tmp]# ./tst2.awk -F: min=100 max=500 passwd
systemd-network 192
abrt 173


實例:

對fstab文件取單詞並計數排序

[root@localhost tmp]# cat /etc/fstab |tr "[:punct:]"  " " |awk '{split($0,arr," ");for(i in arr){brr[arr[i]]++ }} END{for(k in brr){print brr[k],k}} '|sort -nr
6 UUID
6 defaults
5 xfs
3 8
2 swap
2 fstab
2 by
1 Wed
1 var
1 under
1 See
1 reference
1 pages

提取字符串中數字

[root@localhost tmp]# echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk -F "[^[:digit:]]" '{for(i=1;i<=NF;i++){printf "%s",$i}}'
05973


[root@localhost tmp]# ss -ntl|awk -F "[ :]" '/^[^S]/ {arr[$6]++}END{for(i in arr){print arr[$i],i}}'|sort -nr


去掉一個最高一個最低求平均值

馮泉    100     100     96      95      100     96      100     97
萬永振  100     95      90      88      95      98      95      98
徐亮偉  100     100     90      98      90      98      100     96
曹雅楠  100     100     95      90      97      90      95      98
陳派宇  90      95      95      96      100     98      100     96
李峯    90      90      90      85      92      95      95      98
餘連輝  90      93      95      92      95      95      96      95
侯亞光  90      96      97      90      90      85      95      90
王續    85      92      98      98      90      95
蔚雷    92      92      96      90      90      80
蘇浩智  88      96      85      95      90      90
徐登輝  85      95      88      90      90      90
林章益  91      97      98      90      100     90
黃品清  85      97      88      90      90      90
李健    85      95      90      88      80      80
宮全樂  88      95      90      88      90      100
萬良    89      95      95      88      100     100
馬自強  88      97      90      88      90      90
任冠亞  88      97      98      90      100     100

解法1

[root@localhost tmp]# cat awk_tst.tst |awk '{for(i=2;i<=NF;i++){a[i]=$i};sum=0;tmp=0;for(j in a){for(k in a){if(a[k]>a[j]){tmp=a[k];a[k]=a[j];a[j]=tmp;}}}for(s=2;s<length(a);s++){sum+=a[s]};arr=sum/(length(a)-2);print $1,arr;delete a}'


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