天天看點

Shell awk指令

awk 文法結構

awk [options] 'commands' file(s) 

option:
    -F 定義字段分割符号
    -v 定義變量并指派
command:
    1、範圍說明或者正規表達式或者{awk指令語句1;awk指令語句2;}
    2、範圍說明部分可以是BEGIN、END、邏輯表達式或者為空
    3、awk指令語句間用分号間隔
    4、引用shell變量時需要用雙引号引起,指令模式都在單引号''裡面
    
    BEGIN{}    {}        END{}
    行處理前     行處理    行處理後           

複制

字段分割及相關變量

$1,$2,$3...$n:awk中用該順序形式表示files中每行以間隔符号分割的各列的不同字段
$0             表示文本本身
NF             表示目前記錄的字段數(列數)
$NF            最後一列
$(NF-1)        倒數第二列
FNR/NR         行号
FILENAME       檔案名
"\t"           制表符
RS/ORS         換行符            
""             列印字元串
FS/OFS         定義間隔符
~              比對,與==相比不是精确比較
!~             不比對,不精确比較
==             等于,必須全部相等,精确比較
/[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    #輸入字段分隔符,預設為空格           

複制

分隔符

[root@linux /]# echo "aa bb cc"|awk '{print $2}'  #分隔空格
bb
[root@linux /]# echo "aa bb cc"|awk -F " " '{print $2}'  #分隔空格
bb
[root@linux /]# awk -F: '{print $1}' /etc/passwd|wc -l  #統計系統使用者數
33           

複制

指定多個分隔符

[root@linux /]# echo "11 22 33:44:55"|awk -F"[ :]" '{print $2}'
22

[root@linux /]# echo "11-22-33:44:55"|awk -F"[-:]" '{print $3}'
33           

複制

使用FS和OFS指定分隔符

[root@linux /]# echo "aaa222bbb"|awk 'BEGIN{FS="222";OFS=":"}{print $2}'
bbb
[root@linux /]# head -1 /etc/passwd >passwd
[root@linux /]# awk -F: 'BEGIN{OFS="-"}{print $1,$2,$3}' passwd 
root-x-0           

複制

換行符

[root@linux /]# cat xxx.txt 
127.0.0.1
[root@linux /]# awk 'BEGIN{RS="."}{print $0}' xxx.txt
127
0
0
1

[root@linux /]# cat xxx.txt 
127.0.0.1
hello
world
[root@linux /]# awk 'BEGIN{ORS=" "}{print $0}' xxx.txt  #将多行内容合并成一行
127.0.0.1 hello world           

複制

格式化輸出

print函數

[root@linux /]# date|awk '{print "Year:" $NF "\nMonth:" $2 "\nDay:" $3}' #顯示年月日
Year:2020    
Month:Aug
Day:15
[root@linux /]# awk -F: '{print "User:" $1 "\t Shell:" $NF}' /etc/passwd
[root@linux /]# awk -F: '{print "\User: " $1,$NF}' /etc/passwd           

複制

printf函數

awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}'  /etc/passwd
awk -F: '{printf "|%15s| %10s| %15s|\n", $1,$2,$3}' /etc/passwd
awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd           

複制

參數解釋:

%s 字元類型  strings            %-20s
%d 數值類型 
占15字元
- 表示左對齊,預設是右對齊
printf預設不會在行尾自動換行,加\n
awk的模式和動作           

複制

正規表達式

awk '/^root/' /etc/passwd  #比對root開頭的行
awk '!/^root/' /etc/passwd #比對除了root開頭的行           

複制

模式比對表達式

awk -F: '$1 ~ /^admin/'  /etc/passwd
awk -F: '$NF !~ /nologin/'  /etc/passwd           

複制

比較表達式

比較表達式采用對文本進行比較,隻有當條件為真,才執行指定的動作。比較表達式使用關系運算符,用于比較數字與字元串

運算符            含義
<                小于
<=               小于或等于
==               等于
!=               不等于
>=               大于等于
>                大于           

複制

[root@linux /]# awk -F: '$1 == "root" ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@linux /]# awk -F: '$NF == "/bin/bash" ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
admin:x:1000:1000::/home/admin:/bin/bash
[root@linux /]# awk -F: '$3 < 10 ' /etc/passwd           

複制

運算符

+  -  *  /  加減乘除           

複制

[root@linux /]# cat xxx.txt 
10 2
[root@linux /]# awk '{print $1 / $2}' xxx.txt  #除
5
[root@linux /]# awk '{print $1 * $2}' xxx.txt  #乘
20
[root@linux /]# awk '{print $1 - $2}' xxx.txt  #減
8           

複制

邏輯運算符

&&        邏輯與        a&&b
||        邏輯或        a||b
!         邏輯非        !a           

複制

[root@linux /]# awk -F: '$3==0 && $NF=="/bin/bash" {print $1 "\t" $NF}' /etc/passwd
root    /bin/bash
[root@linux /]# awk -F: '$3==0||$NF=="/bin/bash" {print $1 "\t" $NF}' /etc/passwd
root    /bin/bash
admin    /bin/bash
[root@linux /]# awk -F: '!($3 == 0 || $3 <=10)' /etc/passwd           

複制

awk腳本模式

條件判斷

if語句

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

複制

[root@linux /]# awk -F: '{if($3==0){print $1 "\tadmiinistrator"}}' /etc/passwd 
root    admiinistrator

[root@linux /]# awk -F: '{if($1){count++}} END{print count}' /etc/passwd  #統計系統使用者數
45

[root@linux /]# awk 'BEGIN{if('$(id -u)'==0) {print "administrator"} }' 
administrator           

複制

if...else語句

格式:

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

複制

[root@linux /]# awk -F: '{if($3==0){print $1"\t這是管理者"}else{print $1"\t這是普通使用者"}}' /etc/passwd

[root@linux /]# awk -F: '{if($3==0){x++} else{i++}} END{print "管理者個數: "x ; print "系統使用者數: "i}' /etc/passwd
管理者個數: 1
系統使用者數: 32           

複制

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

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

複制

awk -F: '{if($3==0){print "我是管理者使用者"$1}else if($3<999){print "我是系統使用者"$1}else if($3>1000){print "我是普通使用者"$1}}' /etc/passwd           

複制

循環

while循環

awk 'BEGIN{i=1; while(i<=10){print i; i++}}'
awk 'BEGIN{ip="192.168.1."; i=1; while(i<255){print ip i;i++}}'           

複制

for循環

awk 'BEGIN{for(i=0;i<5;i++){print i}}'   
awk 'BEGIN{for(i=1;i<=5;i+=2){print i}}'
awk -F: '{for(i=1;i<=10;i++) print $0}' /etc/passwd             

複制

數組

[root@linux /]# awk -F: '{user[i++]=$1}END{print user[0]}' /etc/passwd
root
[root@linux /]# awk -F: '{user[i++]=$1}END{print user[1]}' /etc/passwd
bin
[root@linux /]# awk -F: '{user[i++]=$1}END{print user[2]}' /etc/passwd
daemon
[root@linux /]# cat /etc/passwd|head -3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin           

複制

數組周遊

統計Shell

[root@linux /]# awk -F: '{shell[$NF]++}END{for(i in shell){print i,shell[i]}}' /etc/passwd
/bin/sync 1
/bin/bash 2
/sbin/nologin 25
/sbin/halt 1
/sbin/shutdown 1           

複制

統計登入SSH失敗的使用者

[root@linux /]# lastb|awk '{name[$1]++}END{for(i in name){print i,name[i]}}'|sort -k2rn|head -3
root 393
ubuntu 92
test 90           

複制

統計網站通路狀态

[root@linux /]# ss -an|grep :80|awk '{x[$2]++}END{for(i in x){print i,x[i]}}'|sort -k2rn
ESTAB 24
TIME-WAIT 3
LISTEN 1           

複制