####################################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 功能與grep相似,比grep功能多
awk 原理和語法格式與sed相似
awk [選項] ‘條件{指令}’ 文件
多條命令用分號隔開;print是最經常使用的指令;
沒有指令默認爲打印所有符合條件的內容
#######################################
例如:取每一行的第三個字:awk ‘{print $3}’ a.txt
輸出內存大小(注意內存會實時變化):free | awk ‘/Mem/{print $4}’
提取根分區剩餘容量df;內存剩餘容量free;cpu負載uptime(最近1、5、15分鐘負載,至關於top的第一行)(linux容許超負載);網卡流量ifconfig(RX 發送包,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文件內以127或192開頭的記錄
# 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
#######################################
awk的if語句
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小於或等於500、UID大於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
#######################################
awk的while循環
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 /對比字節
#######################################
本案例要求使用awk工具完成下列過濾任務:
練習awk工具的基本用法
提取本機的IP地址、根分區使用率
格式化輸出/etc/passwd文件中的用戶名、UID、宿主目錄信息
格式化輸出passwd文件內容時,要求第一行爲列表標題,最後一行提示一共已處理文本的總行數,如圖-1所示。
圖-1
實現此案例須要按照以下步驟進行。
步驟一:awk文本過濾的基本用法
1)基本操做方法
格式:awk [選項] '[條件]{編輯指令}' 文件
其中,print 是最經常使用的編輯指令;如有多條編輯指令,可用分號分隔。
處理文本時,若未指定分隔符,則默認將空格、製表符等做爲分隔符。
直接過濾文件內容:
[root@svr5 ~]# awk '{print $1,$2}' /etc/rc.local //輸出文件的第1、2列
#!/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}' //輸出第1、3、12字段
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.
本案例要求使用awk工具完成下列過濾任務,注意awk處理條件的設置:
列出UID間於501~505的用戶詳細信息
輸出/etc/hosts文件內以127或192開頭的記錄
列出100之內整數中7的倍數或是含7的數
實現此案例須要按照以下步驟進行。
步驟一:認識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
.. ..
本案例要求編寫腳本getupwd-awk.sh,實現如下需求:
找到使用bash做登陸Shell的本地用戶
列出這些用戶的shadow密碼記錄
按每行「用戶名 --> 密碼記錄」保存到getupwd.log,如圖-2所示
圖-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 --> !!
.. ..
本案例要求瞭解awk的流程控制操做,可自行設置awk語句來有驗證如下操做:
if分支結構(雙分支、多分支)
while循環結構
break、continue等其餘控制語句
實現此案例須要按照以下步驟進行。
步驟一: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
本案例要求使用awk工具完成下列兩個任務:
分析Web日誌的訪問量排名,要求得到客戶機的地址、訪問次數,而且按照訪問次數排名
1)awk統計Web訪問排名
在分析Web日誌文件時,每條訪問記錄的第一列就是客戶機的IP地址,其中會有不少重複的IP地址。所以只用awk提取出這一列是不夠的,還須要統計重複記錄的數量而且進行排序。
經過awk提取信息時,利用IP地址做爲數組下標,每遇到一個重複值就將此數組元素遞增1,最終就得到了這個IP地址出現的次數。
針對文本排序輸出能夠採用sort命令,相關的常見選項爲-r、-n、-k。其中-n表示按數字順序升序排列,而-r表示反序,-k能夠指定按第幾個字段來排序。
實現此案例須要按照以下步驟進行。
步驟一:統計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
.. ..