awk基本用法

shell 腳本編程

####################################html

回顧:mysql

sed 文本編輯器,逐行處理,非交互linux

sed [選項]  ‘條件指令’  文件正則表達式

選項:sql

-n  屏蔽默認輸出shell

-i  修改原文件編程

-r 支持擴展正則vim

 

條件:行號,/正則/數組

指令:增刪改查bash

 

a  行前面寫入

i  行後面寫入

d 刪除行  dd

s  s///    變相刪除

c  修改行3c  /root/c

s  s///

p  打印、輸出

r  導入

w 導出

####################################

 

sed 複製剪切:   H   追加   複製   ;  h   覆蓋   複製

                          G   追加   粘貼  ; g   覆蓋   粘貼

 

sed  -n  ‘3h;6g’    a.txt  複製第3行內容覆蓋插入到第6(本來的第6行沒了)

sed  -n  ‘3h;6G’   a.txt  複製第3行內容插入到第6行下面 (本來的第6行還在)

sed  -n  ‘3H;6g’   a.txt  複製第3行內容覆蓋插入到第6行並先空一行(本來的第6行沒了)

sed  -n  ‘3H;6G’  a.txt  複製第3行內容插入到第6行下面並先空一行 (本來的第6行還在)

####################################

1、awk基本用法    

1.awk命令解析

1)主要用法

awk 功能與grep相似,比grep功能多

awk 原理和語法格式與sed相似    

awk  [選項]    ‘條件{指令}’   文件

多條命令用分號隔開;print是最經常使用的指令;

沒有指令默認爲打印所有符合條件的內容

#######################################

 

例如:取每一行的第三個字:awk  ‘{print  $3}’ a.txt

輸出內存大小(注意內存會實時變化):free  |  awk  ‘/Mem/{print  $4}’  

提取根分區剩餘容量df;內存剩餘容量freecpu負載uptime(最近1515分鐘負載,至關於top的第一行)linux容許超負載);網卡流量ifconfigRX 發送包,TX接受包);

num=`df | awk '/\/$/{print $4}'`     (以根結尾的)

 df -hT / | tail -1  | awk '{print $6}'

free | awk '/Mem/{print $4}'

uptime  | awk  '{print $10}'

ifconfig enp2s0  |  awk  ‘/pack/{print  $5}’

==ifconfig enp2s0 | grep "inet  " | awk '{print $2}'

#######################################

 

網頁實時更新根分區剩餘容量、內存剩餘容量、CPU負載、網卡流量等

yum -y install  httpd     systemctl  restart/enable  

vim a.txt

echo 'Content-Type:text/html'

echo ''

echo ''

 

echo "根分區剩餘容量爲:"

df | awk '/\/$/{print $4}'

echo "</br>"

echo "內存剩餘容量爲:"

free | awk  '/Mem/{print $4}'

echo "</br>"

echo "CPU負載爲:"

uptime  | awk '{print $8,$9,$10}'

echo "</br>"

echo "網卡流量爲:"

ifconfig enp2s0 | awk '/pack/{print $5}'

echo "</br>"

腳本存放位置:/var/www/cgi-bin  ,給個x權限,每刷新下網頁腳本就會運行下;關閉selinux;刷新網頁F5

firefox  http://172.40.55.11x/cgi-bin/test.sh

#######################################

 

篩選不以空格分隔的文檔

-F  :指定分隔符(不寫默認爲空格或tab)

指定分隔符爲冒號:

 awk -F: '/^roo/{print $1,$2,$3,$4,$5}'  /etc/passwd

 

awk的內置變量:

$0 一整行(全文)

$1  1列  ; $2  2... ...

NF  當前行有幾列,逐行處理(列數)

NR  當前行的行號(行數)

FNR 記錄當前處理行在原文本內的序號(行號)

FS  保存或設置分隔符,FS=「

 

 awk '{print NF}' a.txt

#######################################

 

tailf  /var/log/secure

回車<屏幕變空白>

其餘主機:ssh  該虛擬機   <輸入錯誤密碼>

 

對公網開放防止遠程登陸及破解密碼:找出登陸失敗的ip,並放入防火牆

 

while :

do

if  在裏面就再也不導了

awk  ‘/Failed/{print $11}’  /var/log/secure  | grep -v  「[a-Z]」  >>ip.txt

for i in $(cat ip.txt)

do

加到防火牆

done

sleep  300

done

#######################################

 

支持直接常量,常量變量混搭:

awk  -F:    ‘{print 「hello」$1}’ /etc/passwd     /這個文件有多少行就輸出多少次,雙引號,hello+用戶名

 

awk 完整語法:能夠單獨使用,也能夠一塊兒使用

awk  ‘BEGIN{}   條件{}  END{}’   文件

begin{}  後面的命令,在讀取文件內容以前執行,只執行一次   /初始化

條件{}     讀取文件的過程當中執行,執行n次(文件的行數)    /處理

END{}    讀取文件的過程後執行,只執行一次                       /總結

 

awk  ‘BEGIN{i=0}   /[0-9]/{i++}   END{print i}’    文件

awk 'BEGIN{x=0}/\<bash$/{x++} END{print x}' /etc/passwd

== egrep   -c    '\<bash$' /etc/passwd   /-c統計匹配的行數

awk  ‘BEGIN{x=1.2;print x/2}       /能夠作算術運算

awk  ‘BEGIN{print 1000/2}       /能夠常量或變量

#######################################

 

分析能登陸計算機的用戶有多少?(有bash解釋器)

awk  ‘BEGIN{i=0}   /bash$/{i++}    END{print i}’    /etc/passwd

awk的變量不用定義,能夠直接調用。默認字串:空;初始數值:0

awk  ‘  /bash$/{i++}    END{print i}’    /etc/passwd

#######################################

 

用戶名     UID     Shell

root         0         /bin/bash

user1      500     /sbin/nologin

總共用戶量:xx                                      (\t  tab)

 

awk  -F  ‘BEGIN{print  「用戶名\tUID\tshell」}    /bash$/{print  $1」\t」$3」\t」$7;x++}  END{print  「總共用戶量:」,x}’    /etc/passwd    

     

       awk -F: 'BEGIN{print "User\tUID\tHome"} {print $1"\t"$3"\t"$6}  END{print "Total"NR"lines."}'  /etc/passwd

#######################################

 

UID/GID範圍: cat /etc/login.defs  ~包含  ;)

 

條件的表現形式:正則表達式、數值/字符串比較、邏輯比較、運算符

模糊匹配:awk  -F:  ‘$1~/root/{print $1}’   /僅對第一列匹配(正則包含便可)

精確匹配:awk  -F:  ‘$1==」root「{print $1}’

精確匹配:awk  -F:  ‘$3>=1000{print $1}’

 

NR==2  當前行爲第二行

NF>=2   包含兩個及以上字段的行

awk   -F:   ‘$3>1000||$3<10’    /etc/passwd             /支持&&||

#######################################

 

練習:ftp://172.40.50.118/share/shell/SHELL/

awk_exam.pdf  grade.txt

 

顯示不包含 Brown 的行

awk '$0 !~ /Brown/' grade.txt

當第一列的第四個字符是 a ,顯示該行

awk '$1 ~/^...a/' grade.txt    

當第六列大於第七列是,顯示$6 大於 $7

awk '$6 > $7 {print $6,"大於",$7}' grade.txt       

顯示包含 Yellow Brown 的行                

awk '$0 ~/(Yellow|Brown)/' grade.txt    awk '$0 ~/Yellow/||/Brown/' grade.tx

顯示文檔第一列、第六列、第七列,若是第一列是 M.Tansley,則先將其第六列的值減 1 後再輸出

awk '{if($1=="M.Tansley") $6=$6-1; print $1,$6,$7}' grade.txt     

 

awk   /San/   data.txt   顯示包含San的行

 

列出UID間於501~505的用戶詳細信息

# awk  -F:  ‘($3>=501)&&($3<=505)’   /etc/passwd

輸出/etc/hosts文件內以127192開頭的記錄

# awk '/^(172|127)/'  /etc/hosts  或  awk '/^127/||/^172/'  /etc/hosts

列出100之內整數中7的倍數或是含7的數

# seq  100 |  awk  ‘/7/||$1%7==0’

seq 100 | awk 'NR%7==0||NR~/7/'

seq 100 | awk '$0%7==0||$0~/7/'

seq 100 | awk '$1%7==0||$1~/7/'

#######################################

 

綜合應用

找到使用bash做登陸Shell的本地用戶

1.passwd裏把能登陸的用戶提取出來

2.shadow裏把他們的密碼取出來

#!/bin/bash

user=`awk  -F:  ‘/bash$/{print  $1}’  /etc/passwd`          /注意反引號

for  i  in  $user

do

awk  -F:   -v   x=$i   ‘$1==x{print  $1,$2}’    /etc/shadow

 

done

 

 

-v  調用外部shell變量

awk  -v  x=10  ‘{print x}’   /etc/hosts    /加文件以逐行處理

#######################################

 

awk -F: '{print $1","$7}' passwd.txt

輸出第3行(行號NR等於3)的用戶記錄:awk -F: 'NR==3' passwd.txt

輸出奇數行(行號NR除以2餘數爲1)的用戶記錄:awk -F: 'NR%2==1'  passwd.txt

輸出前3行文本:awk -F: 'NR<=3' passwd.txt

輸出從第5行開始到文件末尾的全部行:awk -F: 'NR>=5' passwd.txt

輸出UID小於3或者UID是偶數的用戶記錄: awk -F: '$3<=3||$3%2==0' passwd.txt

 

輸出當前用戶的用戶名、宿主目錄、登陸Shell信息:

awk -F: '$1==ENVIRON["USER"]{print $1,$6,$7}' passwd.txt

 

 

#######################################

 

day07

 

awk:編程語言

 

回顧:

awk數據過濾軟件(grep

處理列【條件:/正則/,字符,數字,&&||

awk ‘BEGIN{}  條件{}    END{}’    文件

         ==     !=      >=     >     <      <=

           -eq    -gt    -ge     shell

awk  -F:  ‘/root/{print $1,$3}’   passwd

awk -F:  ‘$1==’root’{print $1,$3}’   passwd

#######################################

 

awkif語句

 

if(判斷){}

if(){}  else{}     ;      if(){}  else if(){} else{}

awk ‘BEGIN{if..}  條件{if..}    END{if..}’    文件

awk對空格沒嚴格要求,不識別單引號

 

統計/etc/passwd文件中UID小於或等於500的用戶個數:

 awk -F: 'BEGIN{i=0}{if($3<=500){i++}}END{print i}'  /etc/passwd

 

分別統計/etc/passwd文件中UID小於或等於500UID大於500的用戶個數:

awk -F: 'BEGIN{i=0;j=0}  {  if($7~/bash$/){i++}  else{j++}  }  END{print i,j}'  /etc/passwd

 

分別統計/etc/passwd文件中登陸Shell是「/bin/bash」、「/sbin/nologin」、其餘的用戶個數:

awk -F: 'BEGIN{i=0;j=0;k=0} {if($7~/bash$/){i++}else if($7~/nologin$/){j++}else{k++}}  END{print i,j,k}'  /etc/passwd

#######################################

 

awkwhile循環

 

while(){}

awk ‘BEGIN{while..}  條件{while..}    END{while..}’    文件

 

求詞頻:

:」或「/」作分隔,針對每一行的每一列進行比對,若是包含「root」,則次數加1。其中,逐行處理直接由awk完成,逐列處理交給while循環,經過i變量依次取$1$2、……、$NF進行檢查;變量j在預處理時賦值0,沒匹配一個字段加1

awk -F [:/] 'BEGIN{j=0}{i=1} {while(i<=NF){if($i~/root/){j++};i++}}  END{print j}'  /etc/passwd

awk -F  [:/] '  {i=1; while(i<=NF){if($i~/root/){j++};i++}}  END{print j}'  /etc/passwd

 

echo $(cat /etc/passwd) | awk -F   "root"  '{print NF-1}'

#######################################

 

awk的數組、for循環

 

awk的下標能夠是數字或字串;awk的下標能夠不定義;

awk  {a[0]=11;a[2]=88; print a[0],a[2]}

awk  {a[nihao]=11;a[chen]=88; print a[0],a[2]}

 

公式:(除$1外,其餘都不變)

awk  '{ip[$1]++}’     /IP[$1]數組變量

who   |  awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}'      /看用戶登陸狀況

awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}'  /var/log/httpd/access_log

 

 

分析Web日誌的訪問量排名,要求得到客戶機的地址、訪問次數,而且按照訪問次數排名

針對文本排序輸出能夠採用sort命令,相關的常見選項爲-r-n-k。其中-n表示按數字順序升序排列,而-r表示反序,-k能夠指定按第幾個字段來排序。

awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log | sort -nr -k 2

 

#######################################

 

準備工做:

服務端:(真機)

yum -y install   httpd  

systemctl  start  httpd

ls  -lh   /var/log/httpd/access_log    

wc  -l   /var/log/httpd/access_log

curl  http://192.168.4.254/        /本身訪問本身

 

客戶機:

yum  -y install   httpd-tools

ab   -c   100  -n   10000   http://192.168.4.254/     /ab最大併發2萬次

 

DOS攻擊【deny of service

 

回服務端:(svr7)

vim  /var/log/httpd/access_log

wc  -l   /var/log/httpd/access_log     /對比

ls  -lh   /var/log/httpd/access_log    /對比字節

#######################################

 

 

 

 

 

 

 

 

 

 

 

Top 

NSD SHELL DAY06

案例1:使用awk提取文本 

案例2awk處理條件 

案例3awk綜合腳本應用 

案例4awk流程控制 

案例5awk擴展應用 

1 案例1:使用awk提取文本

1.1 問題

本案例要求使用awk工具完成下列過濾任務:

練習awk工具的基本用法

提取本機的IP地址、根分區使用率

格式化輸出/etc/passwd文件中的用戶名、UID、宿主目錄信息

格式化輸出passwd文件內容時,要求第一行爲列表標題,最後一行提示一共已處理文本的總行數,如圖-1所示。

 

-1

1.2 步驟

實現此案例須要按照以下步驟進行。

步驟一:awk文本過濾的基本用法

1)基本操做方法

格式:awk [選項] '[條件]{編輯指令}' 文件

其中,print 是最經常使用的編輯指令;如有多條編輯指令,可用分號分隔。

處理文本時,若未指定分隔符,則默認將空格、製表符等做爲分隔符。

直接過濾文件內容:

[root@svr5 ~]# awk '{print $1,$2}' /etc/rc.local      //輸出文件的第12

#!/bin/sh

#

# This

# You

# want

 

touch /var/lock/subsys/local

結合管道過濾命令輸出:

[root@svr5 ~]# uname -a                              //正常的完整輸出

Linux svr5.tarena.com 2.6.18-348.el5 #1 SMP Wed Nov 28 21:22:00 EST 2012 x86_64 x86_64 x86_64 GNU/Linux

[root@svr5 ~]# uname -a | awk '{print $1,$3,$12}'      //輸出第1312字段

Linux 2.6.18-348.el5 x86_64

2)選項 -F 可指定分隔符

截取/etc/passwd文件的前7行,用來建立一個測試文件,操做以下:

[root@svr5 ~]# head -7 /etc/passwd > passwd.txt

[root@svr5 ~]# cat passwd.txt

root:x:0:0:root:/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

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

輸出passwd.txt文件中以分號分隔的第一、7個字段,顯示的不一樣字段之間以逗號隔開,操做以下:

[root@svr5 ~]# awk -F: '{print $1","$7}' passwd.txt

root,/bin/bash

bin,/sbin/nologin

daemon,/sbin/nologin

adm,/sbin/nologin

lp,/sbin/nologin

sync,/bin/sync

shutdown,/sbin/shutdown

或者:

[root@svr5 ~]# awk -F ":" '{print $1","$7}' passwd.txt

root,/bin/bash

bin,/sbin/nologin

daemon,/sbin/nologin

adm,/sbin/nologin

lp,/sbin/nologin

sync,/bin/sync

shutdown,/sbin/shutdown

awk還識別多種單個的字符,好比以「:」或「/」分隔,輸出第一、10個字段:

[root@svr5 ~]# awk -F [:/] '{print $1,$10}' passwd.txt

root bash

bin nologin

daemon nologin

adm sbin

lp

sync sync

shutdown shutdown

輸出每次處理的行號,以及當前行以「:」分隔的字段個數:

[root@svr5 ~]# awk -F: '{print NR,NF}' passwd.txt

1 7

2 7

3 7

4 7

5 7

6 7

7 7

3)awk處理的時機

awk會逐行處理文本,支持在處理第一行以前作一些準備工做,以及在處理完最後一行以後作一些總結性質的工做。在命令格式上分別體現以下:

行前處理,BEGIN{ }

逐行處理,{ }

行後處理,END{ }

上述編輯指令段能夠包含在一對單引號內,好比:

awk  [選項]  ' BEGIN{編輯指令 } {編輯指令} END{編輯指令}'  文件

只作預處理的時候,能夠沒有操做文件,好比:

[root@svr5 ~]# awk 'BEGIN{A=1024;print A*2.56}'

2621.44

舉個包括三個處理時機的例子——「統計系統中使用bash做爲登陸Shell的用戶總個數:預處理時賦值變量x=0,而後逐行讀入 /etc/passwd文件檢查,若是發現登陸Shell是/bin/bash則x增長1,所有處理完畢後,輸出x的值便可。相關操做及結果以下:

[root@svr5 ~]# awk 'BEGIN{x=0}/\<bash$/{x++} END{print x}' /etc/passwd

29

固然,這個例子比較簡單(效果與egrep -c '\<bash$' /etc/passwd 相同),此處僅僅是用來講明awk三種處理時機的用法。在實際工做中,利用awk的這種處理流程能夠完成許多更復雜的任務。

步驟二:利用awk提取本機的IP地址、根分區使用率

1)提取IP地址

分步實現的思路及操做參考以下——

經過ifconfig eth0查看網卡信息,其中包括IP地址:

[root@svr5 ~]# ifconfig eth0

eth0      Link encap:Ethernet  HWaddr 00:0C:29:82:09:E9

          inet addr:192.168.4.4  Bcast:192.168.4.255  Mask:255.255.255.0

          inet6 addr: fe80::20c:29ff:fe82:9e9/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

          RX packets:358524 errors:0 dropped:0 overruns:0 frame:0

          TX packets:230638 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:44470760 (42.4 MiB)  TX bytes:64236279 (61.2 MiB)

結合grep得到包含IP地址的那一行:

[root@svr5 ~]# ifconfig eth0 | grep "inet addr:"

          inet addr:192.168.4.4  Bcast:192.168.4.255  Mask:255.255.255.0

再結合awk過濾出默認分隔的第2列:

[root@svr5 ~]# ifconfig eth0 | grep "inet addr:" | awk '{print $2}'

addr:192.168.4.4

進一步結合awk過濾出以「:」分隔的第2列:

[root@svr5 ~]# ifconfig eth0 | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}'

192.168.4.4

2)提取根分區使用率

分步實現的思路及操做參考以下——

經過df命令查看根分區的使用狀況,其中包括使用率:

[root@svr5 ~]# df -hT /

文件系統         類型     容量     已用     可用     已用%     掛載點

/dev/sda2     ext3     19G         7.2G     11G         40%         /

輸出上述結果中最後一行的第6列:

[root@svr5 ~]# df -hT / | tail -1 | awk '{print $6}'

40%

步驟三:格式化輸出/etc/passwd文件

1)任務需求及實現思路分析

根據任務要求的結果,輸出的內容包括三個部分:列表頭、用戶信息、列表尾。

因爲/etc/passwd文件中的用戶記錄是單一的以「:」分隔,並且剛好awk自己就已經支持「前、中、後」三段式處理,因此用awk處理是再合適不過了。經過awk的內置變量NR便可得到處理的記錄行數,所以只要設置正確的輸出便可。

2)根據實現思路編寫、驗證awk過濾語句

輸出信息時,可使用「\t」顯示Tab製表位:

[root@svr5 ~]# awk -F: 'BEGIN{print "User\tUID\tHome"} \

{print $1"\t"$3"\t"$6} END{print "Total "NR" lines."}' /etc/passwd

User    UID     Home

root    0       /root

bin     1       /bin

daemon  2       /sbin

adm     3       /var/adm

lp      4       /var/spool/lpd

sync    5       /sbin

.. ..

iamkiller       1234    /opt/.private/iamkiller

nsd001  0       /home/nsd001

nsd002  1236    /home/nsd002

nsd003  1237    /home/nsd003

postfix 89      /var/spool/postfix

Total 67 lines.

2 案例2:awk處理條件

2.1 問題

本案例要求使用awk工具完成下列過濾任務,注意awk處理條件的設置:

列出UID間於501~505的用戶詳細信息

輸出/etc/hosts文件內以127192開頭的記錄

列出100之內整數中7的倍數或是含7的數

2.2 步驟

實現此案例須要按照以下步驟進行。

步驟一:認識awk處理條件的設置

建立測試文件passwd.txt文件:

[root@svr5 ~]# head -7 /etc/passwd > passwd.txt

[root@svr5 ~]# cat passwd.txt

root:x:0:0:root:/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

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

1)使用正則表達式設置條件

輸出其中以bash結尾的完整記錄:

[root@svr5 ~]# awk -F: '/bash$/{print}' passwd.txt

root:x:0:0:root:/root:/bin/bash

輸出以a、b、c或d開頭的用戶名、宿主目錄:

[root@svr5 ~]# awk -F: '/^[a-d]/{print $1,$6}' passwd.txt

bin /bin

daemon /sbin

adm /var/adm

輸出其中用戶名以a開頭、登陸Shell以nologin結尾的用戶名、登陸Shell:

[root@svr5 ~]# awk -F: '/^a|nologin$/{print $1,$7}' passwd.txt

bin /sbin/nologin

daemon /sbin/nologin

adm /sbin/nologin

lp /sbin/nologin

輸出其中宿主目錄以bin結尾(對第6個字段作~匹配)的用戶名、宿主目錄信息:

[root@svr5 ~]# awk -F: '$6~/bin$/{print $1,$6}' passwd.txt

bin /bin

daemon /sbin

sync /sbin

shutdown /sbin

輸出其中登陸Shell不以nologin結尾(對第7個字段作!~反向匹配)的用戶名、登陸Shell信息:

[root@svr5 ~]# awk -F: '$7!~/nologin$/{print $1,$7}' passwd.txt

root /bin/bash

sync /bin/sync

shutdown /sbin/shutdown

2)使用數值/字符串比較設置條件

輸出第3行(行號NR等於3)的用戶記錄:

[root@svr5 ~]# awk -F: 'NR==3{print}' passwd.txt

daemon:x:2:2:daemon:/sbin:/sbin/nologin

輸出奇數行(行號NR除以2餘數爲1)的用戶記錄:

[root@svr5 ~]# awk -F: 'NR%2==1{print}' passwd.txt

root:x:0:0:root:/root:/bin/bash

daemon:x:2:2:daemon:/sbin:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

輸出偶數行(行號NR除以2餘數爲0)的用戶記錄:

[root@svr5 ~]# awk -F: 'NR%2==0{print}' passwd.txt

bin:x:1:1:bin:/bin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

輸出前3行文本:

[root@svr5 ~]# awk -F: 'NR<=3{print}' passwd.txt

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

輸出從第5行開始到文件末尾的全部行:

[root@svr5 ~]# awk -F: 'NR>=5{print}' passwd.txt

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

輸出用戶名爲「sync」的行:

[root@svr5 ~]# awk -F: '$1=="sync"{print}' passwd.txt

sync:x:5:0:sync:/sbin:/bin/sync

輸出當前用戶的用戶名、宿主目錄、登陸Shell信息:

[root@svr5 ~]# awk -F: '$1==ENVIRON["USER"]{print $1,$6,$7}' passwd.txt

root /root /bin/bash

3)邏輯測試條件

輸出第3~5行文本:

[root@svr5 ~]# awk -F: 'NR>=3&&NR<=5{print}' passwd.txt

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

嚴謹一點能夠寫成:

[root@svr5 ~]# awk -F: '(NR>=3)&&(NR<=5){print}' passwd.txt

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

輸出第3行和第5行文本:

[root@svr5 ~]# awk -F: 'NR==3||NR==5{print}' passwd.txt

daemon:x:2:2:daemon:/sbin:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

輸出「登陸Shell不以nologin結尾」或者「用戶名以a或d開頭」的文本:

[root@svr5 ~]# awk -F: '$7!~/nologin$/||$1~/^[ad]/{print}' passwd.txt

root:x:0:0:root:/root:/bin/bash

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

輸出UID小於3或者UID是偶數的用戶記錄:

[root@svr5 ~]# awk -F: '$3<3||$3%2==0{print}' passwd.txt

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

4)數學運算

以統計passwd.txt文件中以「:」分隔的總字段個數,須要每處理一行時將當前行的字段數(內置變量NF)計和,所以可在BEGIN時定義一個初始變量,過程稱求和,最後在END時輸出結果。

相關操做及結果以下(共49個字段):

[root@svr5 ~]# awk -F: 'BEGIN{x=0}\

 {x+=NF} END{print "Total "x" fields."}' passwd.txt

Total 49 fields.

步驟二:完成任務要求的awk過濾操做

1)列出UID間於501~505的用戶詳細信息:

[root@svr5 ~]# awk -F: '$3>=501&&$3<=505{print}' /etc/passwd

hunter:x:501:501::/home/hunter:/bin/bash

vina:x:502:502::/home/vina:/bin/bash

kdev:x:503:503::/home/kdev:/bin/bash

zengye:x:504:504::/home/zengye:/bin/bash

stu01:x:505:1201::/tech/nsdhome/stu01:/bin/bash

2)輸出/etc/hosts映射文件內以127或者192開頭的記錄:

[root@svr5 ~]# awk -F: '/^127|^192/{print}' /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

192.168.4.5  svr5.tarena.com svr5

3)列出100之內整數中7的倍數或是含7的數:

此操做無處理文件,正常思路應該是用Shell循環來完成;由於要求用awk來實現,若是不用循環,則根據逐行處理的思路,應該提供一個100行的文本對象,而後將行號做爲處理的整數,逐個判斷並輸出便可。

利用seq命令可生成1-100的整數序列,好比:

[root@svr5 ~]# seq 100

1

2

3

4

5

6

7

8

9

10

.. ..

結合管道交給awk處理,能夠簡化實現步驟。針對本任務而言,行號與每行的實際文本值是一致的,那麼根據NR或者$0行值進行判斷都是能夠的。輸出100之內7的倍數或是包含7的數:

[root@svr5 ~]# seq 100 | awk 'NR%7==0||NR~/7/{print}'

7

14

17

21

27

28

35

37

42

47

.. ..

或者:

[root@svr5 ~]# seq 100 | awk '$0%7==0||$0~/7/{print}'

7

14

17

21

27

28

35

37

42

47

.. ..

3 案例3:awk綜合腳本應用

3.1 問題

本案例要求編寫腳本getupwd-awk.sh,實現如下需求:

找到使用bash做登陸Shell的本地用戶

列出這些用戶的shadow密碼記錄

按每行用戶名 --> 密碼記錄保存到getupwd.log,如圖-2所示

 

圖-2

3.2 步驟

實現此案例須要按照以下步驟進行。

步驟一:任務需求及思路分析

編寫getupwd-awk.sh腳本的任務要求以下:

分析出使用bash做登陸Shell的本地用戶

列出這些用戶的shadow密碼記錄

按每行用戶名 -- 密碼記錄保存結果

步驟二:根據實現思路編寫腳本

複製原getupwd.sh腳本,生成getupwd-awk.sh:

[root@svr5 ~]# cat getupwd.sh                      //確認原腳本內容

#/bin/bash

> /tmp/getupwd.log                                     ## 建立空文件

sed -n '/:\/bin\/bash$/w /tmp/urec.tmp' /etc/passwd      ## 提取符合條件的帳號記錄

UNUM=$(egrep -c '.' /tmp/urec.tmp)                   ## 取得記錄個數

while [ ${i:=1} -le $UNUM ]                         ## 從第1行開始,遍歷帳號記錄

do

    UREC=$(sed -n "${i}p" /tmp/urec.tmp)              ## 取指定行數的記錄

    NAME=${UREC%%:*}                                 ## 截取用戶名(記錄去尾)

    PREC=$(sed -n "/^$NAME:/p" /etc/shadow)          ## 查找與用戶名對應的密碼記錄

    PASS=${PREC#*:}                                  ## 掐頭

    PASS=${PASS%%:*}                                ## 去尾,只留下密碼記錄

    echo "$NAME --> $PASS" >> /tmp/getupwd.log         ## 保存結果

    let i++                                           ## 自增1,轉下一次循環

done

/bin/rm -rf /tmp/urec.tmp                           ## 刪除臨時文件

echo "用戶分析完畢,請查閱文件 /tmp/getupwd.log"         ## 完成後提示

 

[root@svr5 ~]# cp getupwd.sh getupwd-awk.sh          //複製爲新腳本文件

修改新腳本文件,內容參考以下:

[root@svr5 ~]# vim getupwd-awk.sh

#/bin/bash

## 建立空文件

> /tmp/getupwd.log

## 提取用戶名列表

awk -F: '/:\/bin\/bash$/{print $1}' /etc/passwd > /tmp/users.tmp

## 經過for循環遍歷用戶名、查詢密碼記錄,保存結果

for NAME in $(cat /tmp/users.tmp)

do

    grep "^$NAME:" /etc/shadow | awk -F: '{print $1" --> "$2 | \

    "cat >> /tmp/getupwd.log"}' /etc/shadow

done

echo "用戶分析完畢,請查閱文件 /tmp/getupwd.log" ## 完成後提示

 

[root@svr5 ~]# chmod +x getupwd-awk.sh

步驟三:驗證、測試腳本

[root@svr5 ~]# ./getupwd-awk.sh      

用戶分析完畢,請查閱文件 /tmp/getupwd.log

 

[root@svr5 ~]# head -5 /tmp/getupwd.log

root --> $6$IWgMYmRACwdbfwBo$dr8Yn983nswiJVw0dTMjzbDvSLeCd1GMYjbvsDiFEkL8jnXOLcocBQypOCr4C6BRxNowIxjh6U2qeFU0u1LST/

zengye --> $6$Qb37LOdzRl5995PI$L0zTOgnhGz8ihWkW81J.5XhPp/l7x2./Me2ag0S8tRndCBL9nIjHIKkUKulHxJ6TXyHYmffbVgUT6pbSwf8O71

clamav --> !!

mysql --> !!

abc --> !!

.. ..

4 案例4:awk流程控制

4.1 問題

本案例要求瞭解awk的流程控制操做,可自行設置awk語句來有驗證如下操做:

if分支結構(雙分支、多分支)

while循環結構

breakcontinue等其餘控制語句

4.2 步驟

實現此案例須要按照以下步驟進行。

步驟一:awk過濾中的if分支結構

1)單分支

統計/etc/passwd文件中UID小於或等於500的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($3<=500){i++}}END{print i}' /etc/passwd

39

統計/etc/passwd文件中UID大於500的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($3>500){i++}}END{print i}' /etc/passwd

28

統計/etc/passwd文件中登陸Shell是「/bin/bash」的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($7~/bash$/){i++}}END{print i}'\

 /etc/passwd

29

統計/etc/passwd文件中登陸Shell不是「/bin/bash」的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($7!~/bash$/){i++}}END{print i}'\

 /etc/passwd

38

2)雙分支

分別統計/etc/passwd文件中UID小於或等於500、UID大於500的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd

39 28

分別統計/etc/passwd文件中登陸Shell是「/bin/bash」、 登陸Shell不是「/bin/bash」的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0}{if($7~/bash$/){i++}else{j++}}\

END{print i,j}' /etc/passwd

29 38

3)多分支

分別統計/etc/passwd文件中登陸Shell是「/bin/bash」、「/sbin/nologin」、其餘的用戶個數:

[root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0;k=0}{if($7~/bash$/){i++}\

else if($7~/nologin$/){j++}else{k++}}END{print i,j,k}' /etc/passwd

29 33 5

步驟二:awk過濾中的while循環結構

1)while循環

統計/etc/passwd文件內「root」出現的次數。

—— 分析:以「:」或「/」作分隔,針對每一行的每一列進行比對,若是包含「root」,則次數加1。其中,逐行處理直接由awk完成,逐列處理交給while循環,經過i變量依次取$一、$二、……、$NF進行檢查;變量j在預處理時賦值0,沒匹配一個字段加1。

[root@svr5 ~]# awk -F [:/] \

'BEGIN{j=0}\

{i=1}{while(i<=NF){if($i~/root/){j++};i++}}\

END{print j}'  /etc/passwd

4

此例僅爲說明while循環的用法。

實際應用時,上述操做能夠簡單處理,可經過命令替換將文件內容賦值給一個變量(變爲一行文本),而後針對此變量值以目標字符串「root」做爲分隔,獲取總字段數-1便可得目標字符串的總數量:

[root@svr5 ~]# echo $(cat /etc/passwd) | awk -F "root" '{print NF-1}'

4

5 案例5:awk擴展應用

5.1 問題

本案例要求使用awk工具完成下列兩個任務:

分析Web日誌的訪問量排名,要求得到客戶機的地址、訪問次數,而且按照訪問次數排名

5.2 方案

1)awk統計Web訪問排名

在分析Web日誌文件時,每條訪問記錄的第一列就是客戶機的IP地址,其中會有不少重複的IP地址。所以只用awk提取出這一列是不夠的,還須要統計重複記錄的數量而且進行排序。

經過awk提取信息時,利用IP地址做爲數組下標,每遇到一個重複值就將此數組元素遞增1,最終就得到了這個IP地址出現的次數。

針對文本排序輸出能夠採用sort命令,相關的常見選項爲-r、-n、-k。其中-n表示按數字順序升序排列,而-r表示反序,-k能夠指定按第幾個字段來排序。

5.3 步驟

實現此案例須要按照以下步驟進行。

步驟一:統計Web訪問量排名

分步測試、驗證效果以下所述。

1)提取IP地址及訪問量

[root@svr5 ~]# awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log

127.0.0.1 4

192.168.4.5 17

192.168.4.110 13

.. ..

2)對第1)步的結果根據訪問量排名

[root@svr5 ~]# awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log | sort -nr -k 2

192.168.4.5 17

192.168.4.110 13

127.0.0.1 4

.. ..

相關文章
相關標籤/搜索