Awk總結筆記mysql
90年代 new awk :nawkios
Linux 的是gawk 咱們簡化awknginx
# awk [options ] ‘scripts’ file1 file2 ....web
# awk [options ] ‘PATTERN {action }’ file1 file2 ....正則表達式
讀入文本先切片以下 切5片sql
每片$n 整行$0shell
每行片數不同centos
內置變量數組
如下爲awk內置變量:緩存
ARGC 命令行參數個數
FILENAME 當前輸入文檔的名稱
FNR 當前輸入文檔的當前記錄編號,尤爲當有多個輸入文檔時有用
NR 輸入流的當前記錄編號
NF 當前記錄的字段個數
FS 字段分隔符
OFS 輸出字段分隔符,默認爲空格
ORS 輸出記錄分隔符,默認爲換行符\n
RS 輸入記錄分隔符,默認爲換行符\n
示例:
[root@centos5 awk]# cat a.txt
welcome to my heart
i am liujianzuo
how are u?
[root@centos5 awk]# awk '{print $1}' a.txt
welcome
i
How
[root@centos5 awk]# df -hP #顯示到一行
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 7.1G 3.2G 3.6G 48% /
/dev/sda1 198M 13M 176M 7% /boot
tmpfs 63M 0 63M 0% /dev/shm
/dev/sdb1 99M 6.1M 88M 7% /data
[root@centos5 awk]# df -h|awk '{print $1}'
Filesystem
/dev/sda3
/dev/sda1
tmpfs
/dev/sdb1
相似cut -d
[root@centos5 awk]# awk -F : '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
news
uucp
operator
games
gopher
ftp
nobody
nscd
vcsa
pcap
ntp
dbus
[root@centos5 awk]# awk -F : '{print $NF}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
/sbin/halt
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
[root@centos5 awk]# cat a.txt
welcome to my heart
i am liujianzuo
how are u?
[root@centos5 awk]# awk '{print $(NF-2)}' a.txt
to
i
how
[root@centos5 awk]# awk -v FS=: '{print $NF}' /etc/passwd|tail -3
/sbin/nologin
/bin/bash
/bin/bash
[root@centos5 awk]# awk '{print $1 $2}' a.txt
welcometo
iam
howare
[root@centos5 awk]# awk '{print $1,$2}' a.txt
welcome to
i am
how are
[root@centos5 awk]# awk -v OFS=: '{print $1,$2}' a.txt
welcome:to
i:am
how:are
不會自動換行 須要\n
格式符候還能夠加修飾符
以下是每一行開始第一列字段是10個字符對其,第二列字段是1個字符對其,默認右對齊
,不會自動換行
[root@centos5 awk]# awk '{printf "%10s,%s",$1,$2}' a.txt
welcome,to i,am how,are[root@centos5 awk]#
[root@centos5 awk]# awk '{printf "%10s,%s\n",$1,$2}' a.txt
welcome,to
i,am
how,are
[root@centos5 awk]# awk '{printf "%-10s,%-s\n",$1,$2}' a.txt
welcome ,to
i ,am
how ,are
[root@centos5 awk]# awk '{printf "%-10s%-s\n",$1,$2}' a.txt
welcome to
i am
how are
[root@centos5 awk]# awk -F : '{printf "%-10s %i\n",$1,$3 > "/dev/stderr" }' /etc/passwd #改變輸出流,引號引發來
[root@centos5 awk]# awk -F : '{printf "%-10s %i\n",$1,$3 > "/server/scripts/awk/passwd.log" }' /etc/passwd #改變輸出流
[root@centos5 awk]# cat passwd.log
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
news 9
uucp 10
operator 11
games 12
gopher 13
ftp 14
nobody 99
nscd 28
vcsa 69
pcap 77
ntp 38
dbus 81
avahi 70
rpc 32
mailnull 47
smmsp 51
oprofile 16
sshd 74
rpcuser 29
nfsnobody 65534
xfs 43
haldaemon 68
avahi-autoipd 100
oldboy 500
mysql 501
nginx 502
nagios 503
disdata 999
ayibang 1000
這裏y是種模式
[root@centos5 awk]# awk 'BEGIN{print "a" "b"}'
ab
匹配某一行第一個字段是以root開頭的模式咱們就打印第3 4 最後一個字段
[root@centos5 awk]# awk -F : '$1 ~ /^root/ {print $3,$4,$NF}' /etc/passwd
0 0 /bin/bash
for i in read write print;
do
cat file.txt | awk '{ if ($7~/'"$i"'/) {print $0} }'| wc -l ;
done
匹配pation以後是動做以下例子,匹配bash這個模式後動做是打印匹配的包含的所有
# awk [options ] 'PATTERN {action }' file1 file2 ....
[root@centos5 awk]# awk -F : '/bash/ {print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash
oldboy:x:500:500::/home/oldboy:/bin/bash
disdata:x:999:999::/home/disdata:/bin/bash
ayibang:x:1000:1000::/home/ayibang:/bin/bash
[root@centos5 awk]# awk -F : '/bash/ {print $1}' /etc/passwd
root
oldboy
disdata
ayibang
[root@centos5 awk]# awk -F : '$3 >= 500 {print $1}' /etc/passwd
nfsnobody
oldboy
mysql
nginx
nagios
disdata
ayibang
[root@centos5 awk]# awk -F : '$3 >= 500 {print $1,$3}' /etc/passwd
nfsnobody 65534
oldboy 500
mysql 501
nginx 502
nagios 503
disdata 999
ayibang 1000
/bash/,/500/
[root@centos5 ceshi]# awk '/bash|500/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
oldboy:x:500:500::/home/oldboy:/bin/bash
disdata:x:999:999::/home/disdata:/bin/bash
ayibang:x:1000:1000::/home/ayibang:/bin/bash
liujianzuo:x:1001:1001::/home/liujianzuo:/bin/bash
[root@centos5 ~]# awk -F: '$3>=500 {print "USERNAME UID";printf "%-15s%s\n",$1,$3}' /etc/passwd #在awk預讀每一行的時候,都打印一行
USERNAME UID
nfsnobody 65534
USERNAME UID
oldboy 500
USERNAME UID
mysql 501
USERNAME UID
nginx 502
USERNAME UID
nagios 503
USERNAME UID
disdata 999
USERNAME UID
ayibang 1000
[root@centos5 ceshi]# awk -F: 'BEGIN{print "USERNAME UID"} $3 >= 500 {printf "%-15s%s\n",$1,$3}' /etc/passwd
USERNAME UID
nfsnobody 65534
oldboy 500
mysql 501
nginx 502
nagios 503
disdata 999
ayibang 1000
liujianzuo 1001
[root@centos5 ceshi]# awk -F: 'BEGIN{print "USERNAME UID"} {if($3 >= 500) printf "%-15s%s\n",$1,$3}' /etc/passwd
USERNAME UID
nfsnobody 65534
oldboy 500
mysql 501
nginx 502
nagios 503
disdata 999
ayibang 1000
liujianzuo 1001
[root@centos5 ceshi]# awk -F: 'BEGIN{print "USERNAME UID"}{printf "%-15s%s\n",$1,$3}' /etc/passwd
USERNAME UID
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
news 9
uucp 10
operator 11
games 12
gopher 13
ftp 14
nobody 99
nscd 28
vcsa 69
pcap 77
ntp 38
dbus 81
avahi 70
rpc 32
mailnull 47
smmsp 51
oprofile 16
sshd 74
rpcuser 29
nfsnobody 65534
xfs 43
haldaemon 68
avahi-autoipd 100
oldboy 500
mysql 501
nginx 502
nagios 503
disdata 999
ayibang 1000
liujianzuo 1001
[root@centos5 ceshi]# awk -F: 'BEGIN{print "USERNAME UID"} {$3>=500;printf "%-15s%s\n",$1,$3}END{printsswd "END"}' /etc/passwd
USERNAME UID
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
news 9
uucp 10
operator 11
games 12
gopher 13
ftp 14
nobody 99
nscd 28
vcsa 69
pcap 77
ntp 38
dbus 81
avahi 70
rpc 32
mailnull 47
smmsp 51
oprofile 16
sshd 74
rpcuser 29
nfsnobody 65534
xfs 43
haldaemon 68
avahi-autoipd 100
oldboy 500
mysql 501
nginx 502
nagios 503
disdata 999
ayibang 1000
liujianzuo 1001
END
[root@centos5 ceshi]# awk -F : '{print $1}' /etc/passwd |head -1
root
[root@centos5 ceshi]# awk -v FS=: '{print $1}' /etc/passwd |head -1
root
[root@centos5 ceshi]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd |head -1
root
若是if後面是好幾個條件應該用花括號擴起來
[root@centos5 ~]# awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
8
[root@centos5 ~]# awk -F: '{if ($3>=500) print $NF}' /etc/passwd
/sbin/nologin
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/bash
/bin/bash
/bin/bash
[root@centos5 ~]# awk -F: '{if ($3>=500) print $NF}' /etc/passwd|wc -l
8
[root@centos5 ceshi]# awk -F: '{if ($3 == 0) print $1,"Admin";else print $1,"Comman user"}' /etc/passwd
root Admin
bin Comman user
daemon Comman user
adm Comman user
lp Comman user
sync Comman user
shutdown Comman user
halt Comman user
mail Comman user
news Comman user
uucp Comman user
operator Comman user
games Comman user
gopher Comman user
ftp Comman user
nobody Comman user
nscd Comman user
vcsa Comman user
pcap Comman user
ntp Comman user
dbus Comman user
avahi Comman user
rpc Comman user
mailnull Comman user
smmsp Comman user
oprofile Comman user
sshd Comman user
rpcuser Comman user
nfsnobody Comman user
xfs Comman user
haldaemon Comman user
avahi-autoipd Comman user
oldboy Comman user
mysql Comman user
nginx Comman user
nagios Comman user
disdata Comman user
ayibang Comman user
liujianzuo Comman user
[root@centos5 ~]# awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
root
x
0
bin
x
1
daemon
x
2
adm
x
3
lp
x
4
sync
x
5
shutdown
x
6
halt
x
7
x
8
news
x
9
uucp
x
10
operator
x
11
games
x
12
gopher
x
13
ftp
x
14
nobody
x
99
nscd
x
28
vcsa
x
69
pcap
x
77
ntp
x
38
dbus
x
81
avahi
x
70
rpc
x
32
mailnull
x
47
smmsp
x
51
oprofile
x
16
sshd
x
74
rpcuser
x
29
nfsnobody
x
65534
xfs
x
43
haldaemon
x
68
avahi-autoipd
x
100
oldboy
x
500
mysql
x
501
nginx
x
502
nagios
x
503
disdata
x
999
ayibang
x
1000
liujianzuo
x
1001
Awk能夠加pattion 模式的意思,若是不匹配pattion意指其會每行都匹配。
[oldboy@centos5 ~]$ awk -F: '$1 !~ /^root/{i=1;while (i<=2) {print $i;i++}}' /etc/passwd
bin
x
daemon
x
adm
x
lp
x
sync
x
shutdown
x
halt
x
x
news
x
uucp
x
operator
x
games
x
gopher
x
ftp
x
nobody
x
nscd
x
vcsa
x
pcap
x
ntp
x
dbus
x
avahi
x
rpc
x
mailnull
x
smmsp
x
oprofile
x
sshd
x
rpcuser
x
nfsnobody
x
xfs
x
haldaemon
x
avahi-autoipd
x
oldboy
x
mysql
x
nginx
x
nagios
x
disdata
x
ayibang
x
liujianzuo
X
例如我想取第第奇數個字段。咱們遞增i+=2便可
[oldboy@centos5 ~]$ awk -F: '$3 >= 500{i=1;while (i<=4) {print $i;i+=2}}' /etc/passwd
Nfsnobody #第一列
65534 #第三列
Oldboy #第一列
500 #第三列
mysql
501
nginx
502
nagios
503
disdata
999
ayibang
1000
liujianzuo
1001
do-while 不管條件如何,首先會循環一遍,當條件一知足就會退出
[root@centos5 awk]# awk 'BEGIN{i=1;while (i<=100) {sum+=i;print sum;i++}}' |tail -1
5050
awk 'BEGIN{i=1;do {sum+=i;print sum;i++}while(i<=100)}'|tail -1
5050
awk 'BEGIN{i=1;do {sum=sum+i;print sum;i++}while(i<=100)}'|tail -1
5050
awk 'BEGIN{i=1;do {sum+=i;i++}while(i<=100) print sum}'
【元嬰】北京-吳兆 2015/1/11 17:53:30
循環中不輸出,最後輸出結構就好了……
cat filename | nawk -F " " '{for (i=4;i<=NF;i++)printf("%s ", $i);print ""}' 字段不換行 printf
[root@centos5 awk]# awk -F: '$3>=500{for (i=1;i<=NF;i+=2) print $i}' /etc/passwd
awk -F: '$3>=500{for (i=1;i<=NF;i+=2) printf("%s ", $i);print ""}' /etc/passwd
nfsnobody
65534
Anonymous NFS User
/sbin/nologin
oldboy
500
/bin/bash
mysql
501
/sbin/nologin
nginx
502
/sbin/nologin
nagios
503
/sbin/nologin
disdata
999
/bin/bash
ayibang
1000
/bin/bash
liujianzuo
1001
/bin/bash
for打印第奇數個字段
[root@centos5 awk]# awk -F: '$3>=500{for (i=1;i<=5;i+=2) print $i}' /etc/passwd
nfsnobody
65534
Anonymous NFS User
oldboy
500
mysql
501
nginx
502
nagios
503
disdata
999
ayibang
1000
liujianzuo
1001
[root@centos5 awk]# awk 'BEGIN{for (i=i;i<=100;i++) {j=j+i;print j}}'|tail -1
5050
[root@ayibang-server /server/scripts]# awk 'BEGIN{j=0;for (i=1;i<=100;i++) j+=i;{print j}}'
5050
內置變量
如下爲awk內置變量:
ARGC 命令行參數個數
FILENAME 當前輸入文檔的名稱
FNR 當前輸入文檔的當前記錄編號,尤爲當有多個輸入文檔時有用
NR 輸入流的當前記錄編號
NF 當前記錄的字段個數
FS 字段分隔符
OFS 輸出字段分隔符,默認爲空格
ORS 輸出記錄分隔符,默認爲換行符\n
RS 輸入記錄分隔符,默認爲換行符\n
示例:
[liujianzuo@w2 scripts]$ for n in {06..26};do for i in `ls -l /data1/logs/qr* |awk '{print $NF}'`;do wc -l $i|awk -F . '$NF ~ /201507'${n}'/{print $0}';done;done 1 /data1/logs/qrscene_51pro_gz.log.20150707
6 /data1/logs/qrscene_51pro_hz.log.20150707
2 /data1/logs/qrscene_51pro_nj.log.20150707
3 /data1/logs/qrscene_51pro_qd.log.20150707
1 /data1/logs/qrscene_51pro_sh.log.20150707
6 /data1/logs/qrscene_51pro_wh.log.20150707
1 /data1/logs/qrscene_51pro_xa.log.20150707
1 /data1/logs/qrscene_51pro_zz.log.20150707
4 /data1/logs/qrscene_cq_dm.log.20150707
5 /data1/logs/qrscene_cq_sl.log.20150707
17 /data1/logs/qrscene_cs_dm.log.20150707
1 /data1/logs/qrscene_gz_dm.log.20150707
1 /data1/logs/qrscene_gz_szi.log.20150707
6 /data1/logs/qrscene_hz_dm.log.20150707
9 /data1/logs/qrscene_mlyh.log.20150707
2 /data1/logs/qrscene_nj_dm.log.20150707
3 /data1/logs/qrscene_nj_sl.log.20150707
1 /data1/logs/qrscene_qd_szi.log.20150707
1 /data1/logs/qrscene_xa_szi.log.20150707
14 /data1/logs/qrscene_xiaomi.log.20150707
26 /data1/logs/qrscene_xz.log.20150707
4 /data1/logs/qrscene_zz_dm.log.20150707
3 /data1/logs/qrscene_15suit.log.20150708
5 /data1/logs/qrscene_51pro_bj.log.20150708
1 /data1/logs/qrscene_51pro_gz.log.20150708
5 /data1/logs/qrscene_51pro_hz.log.20150708
19 /data1/logs/qrscene_51pro_qd.log.20150708
1 /data1/logs/qrscene_51pro_wh.log.20150708
。。。。。略去n行
http://oldboy.blog.51cto.com/2561410/760192
問題爲:
4)已知:/etc/hosts的內容爲
192.168.1.11 oldboy11.etiantian.org
192.168.1.21 oldboy21.etiantian.org
192.168.1.31 oldboy31.etiantian.org
#192.168.1.111 oldboy111.etiantian.org
請用shell腳本實現,怎麼才能在輸入IP後找到/etc/hosts裏對應的惟一的hostname?
解答:
法1)腳本過濾法
[root@old_boy scripts]# cat judgehost.sh
#!/bin/bash
echo "please input ip address:"
read ip
[ -n "`grep "$ip " /etc/hosts`" ] && \ #注意前面的過濾條件結尾帶有空格。
echo "The hostname is: `grep "$ip " /etc/hosts |awk '{print $2}'`" || \
echo "The ip is invalid"
提示:
1)這是一個grep過濾加條件判斷的實現語法:
2)條件判斷語法爲[ -n "ddd" ] && echo 1 || echo 0
3)[ -n "`grep "$ip " /etc/hosts`" ] && \ #注意前面的過濾條件結尾帶有空格。這裏啊,是爲了排除下面的重複狀況
192.168.1.11 oldboy11.etiantian.org
192.168.1.111 oldboy111.etiantian.org
----------------我是每種方法分隔符---------------
法2)腳本精確匹配法:
#!/bin/bash
#author oldboy
#qq 31333741
#judge input
if [ $# -ne 1 ]
then
echo "input error!"
exit 1
fi
flag=0
exec < /etc/hosts
while read line
do
if [ "$1" = "`echo $line|awk '{print $1}'`" ]
then
flag=1
echo "the $1 's hostname is `echo $line|awk '{print $2}'`"
break;
fi
done
[ $flag -eq 0 ] && echo " sorrry,not find $1 's hostname!"
提示:此題,請你們學習while的用法及設置flag的思路。
執行結果:
[root@old_boy scripts]# sh oldboy.sh 192.168.1.11
the 192.168.1.11 's hostname is oldboy11.etiantian.org
[root@old_boy scripts]# sh oldboy.sh 192.168.1.21
the 192.168.1.21 's hostname is oldboy21.etiantian.org
[root@old_boy scripts]# sh oldboy.sh 192.168.1.311
sorrry,not find 192.168.1.311 's hostname!
----------------我是每種方法分隔符---------------
特別提示:下面的方法中,老男孩老師大量的使用了awk的不一樣方法來實現一樣的功能,來告訴你們,awk是很強大的, 但願同窗們能按照老師的教學要求精通之。
法3)awk精確匹配:
準備:
[root@old_boy scripts]# tail -4 /etc/hosts
192.168.1.11 oldboy11.etiantian.org
192.168.1.111 oldboy111.etiantian.org
192.168.1.21 oldboy21.etiantian.org
192.168.1.31 oldboy31.etiantian.org
腳本:
[root@old_boy scripts]# cat awkhost1.sh
awk 'BEGIN {a="'$1'"} {if($1==a) print $2; }' /etc/hosts
執行結果:
[root@old_boy scripts]# sh awkhost1.sh 192.168.1.21
oldboy21.etiantian.org
[root@old_boy scripts]# sh awkhost1.sh 192.168.1.31
oldboy31.etiantian.org
[root@old_boy scripts]# sh awkhost1.sh 192.168.1.11
oldboy11.etiantian.org
提示:注意a="'$1'"的用法,$1爲命令行傳參。awk程序中調用系統變量的方法a="'$1'"。
----------------我是每種方法分隔符---------------
法4)awk精確匹配法
[root@old_boy scripts]# cat awkhost2.sh
awk '{if($1=="'$1'") print $2}' /etc/hosts
執行結果:
[root@old_boy scripts]# awkhost2.sh 192.168.1.11
oldboy11.etiantian.org
[root@old_boy scripts]# awkhost2.sh 192.168.1.21
oldboy21.etiantian.org
[root@old_boy scripts]# awkhost2.sh 192.168.1.311
----------------我是每種方法分隔符---------------
法5)awk過濾法
[root@old_boy scripts]# cat awkhost4.sh
awk '/'"${1} "'/''{print $2}' /etc/hosts
執行結果:
[root@old_boy scripts]# awkhost4.sh 192.168.1.21
oldboy21.etiantian.org
[root@old_boy scripts]# awkhost4.sh 192.168.1.11
oldboy11.etiantian.org
[root@old_boy scripts]# awkhost4.sh 192.168.1.31
oldboy31.etiantian.org
提示:除了語法外,這道題有個學問,就是過濾時傳參結尾要帶個空格,這樣才能過濾重複IP的狀況
如:
192.168.1.11 oldboy11.etiantian.org
192.168.1.111 oldboy111.etiantian.org
----------------我是每種方法分隔符---------------
法6)awk過濾法
[root@old_boy scripts]# cat awkhost5.sh
awk '{if($1~/'$1'/) print $2}' /etc/hosts ##若是文件第一列包含命令行第一個參數字符則打印第二列
執行結果:
[root@old_boy scripts]# awkhost5.sh 192.168.1.31
oldboy31.etiantian.org
[root@old_boy scripts]# awkhost5.sh 192.168.1.11
oldboy11.etiantian.org
oldboy111.etiantian.org ------>這裏有bug了。
[root@old_boy scripts]# awkhost5.sh 192.168.1.21
oldboy21.etiantian.org
改進下來排除bug:
[root@old_boy scripts]# cat awkhost5-1.sh
awk '{if($1~/'$1' /) print $2}' /etc/hosts ==>用上面加空格的思路不對。
[root@old_boy scripts]# cat awkhost5-1.sh
awk '{if($1~/'$1'$/) print $2}' /etc/hosts #增長一個正則表達式$
執行結果:
[root@old_boy scripts]# awkhost5-1.sh 192.168.1.21
oldboy21.etiantian.org
[root@old_boy scripts]# awkhost5-1.sh 192.168.1.11
oldboy11.etiantian.org
[root@old_boy scripts]# awkhost5-1.sh 192.168.1.31
oldboy31.etiantian.org
----------------我是每種方法分隔符---------------
法7)awk -v精確匹配法
命令行測試:
[root@old_boy scripts]# awk -v p=192.168.1.21 '$1 == p{print $2}' /etc/hosts
oldboy21.etiantian.org
[root@old_boy scripts]# awk -v p=192.168.1.11 '$1 == p{print $2}' /etc/hosts
oldboy11.etiantian.org
[root@old_boy scripts]# awk -v p=192.168.1.11 '$1 == p {print $2}' /etc/hosts
oldboy11.etiantian.org
實際腳本:
[root@old_boy scripts]# cat awkhost6.sh
#!/bin/bash
#p=$1
#awk -v p="$p" '$1 == p{print $2}' /etc/hosts
awk -v p="$1" '$1 == p{print $2}' /etc/hosts
執行結果:
[root@old_boy scripts]# sh awkhost6.sh 192.168.1.11
oldboy11.etiantian.org
[root@old_boy scripts]# sh awkhost6.sh 192.168.1.21
oldboy21.etiantian.org
提示:
1)傳參非awk程序,所以寫法p="$1"
2)man awk
-v var=val
--assign var=val
Assign the value val to the variable var, before execution of the program begins. Such vari-
able values are available to the BEGIN block of an AWK program.
----------------我是每種方法分隔符---------------
法8:精確匹配簡單的寫法
[root@old_boy scripts]# cat awkhost9.sh
awk '$1 == "'$1'" {print $2}' /etc/hosts
執行結果:
[root@old_boy scripts]# sh awkhost9.sh 192.168.1.11
oldboy11.etiantian.org
[root@old_boy scripts]# sh awkhost9.sh 192.168.1.21
oldboy21.etiantian.org
[root@old_boy scripts]# sh awkhost9.sh 192.168.1.31
oldboy31.etiantian.org
特別提示:這裏老男孩老師大量的使用了awk的不一樣方法來實現一樣的功能,很強大吧,
但願同窗們能按照老師的教學要求精通之。
數組就是變量的即集合體
Shell中的打印 echo ${A["x"]} 須要${}才能輸出變量,而awk則不用
下標能夠是任意字符,可是咱們要將字符用引號引發來,以避免被誤認爲變量
以下
[root@centos5 ~]# awk 'BEGIN{A[x]='hello';A[y]='world';print A[x]}'
[root@centos5 ~]# awk 'BEGIN{A["x"]='hello';A["y"]='world';print A[x],A["y"]}'
[root@centos5 ~]# awk 'BEGIN{A["x"]="hello";A["y"]="world";print A[x],A["y"]}'
world
[root@centos5 ~]# awk 'BEGIN{A["x"]="hello";A["y"]="world";print A["x"],A["y"]}'
hello world
Awk的數組不能跟shell的數組同樣,不能一一遍歷,它的元素不都是數字,有多是字符串或者字段
第二個是for循環是awk的遍歷,這裏面的ARRAY是數組,A是咱們定義的變量是數組的下標數字0 1 2 3 。。。 A保存的是咱們數組ARRAY的下標名字
例如
[root@centos5 ~]# awk 'BEGIN{A["x"]="hello";A["y"]="world";for (B in A) print A[B]}' #這裏的B是定義的變量就是A數組的下標號,咱們遍歷A數組,打印全部的元素。B保存的是A數組的下標名字
hello
world
Tcp狀態有好多種,最後一列,咱們用awk實現統計每種狀態的鏈接數 後面有解釋
[root@centos5 ~]# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:2049 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:5666 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:624 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22929 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:52113 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:1012 0.0.0.0:* LISTEN
tcp 0 0 192.168.92.132:52113 192.168.92.1:49262 ESTABLISHED
tcp 0 0 :::52113 :::* LISTEN
Awk的數組組成:數組名字,數組下標,數組元素,數組元素的值。
S[$NF]++ 意思是咱們這個數組S,咱們取最後一列做爲這個數組的下標,所以這個數組就是S[LISTEN] S[ESTABLISHED],每讀取一行,相同元素會疊加
這裏A是數組S的下標名稱,而數組S的下標名稱是TIME_WAIT CLOSE_WAIT FIN_WAIT1 ESTABLISHED 等等。For循環是遍歷的這幾種,因此A就表明這幾個名稱,而S[A]則表明數組元素的值
[ayibang@db2 ~]$ netstat -ant|awk '$1~/tcp/{S[$NF]++}END{for (A in S) print A,S[A]}'
TIME_WAIT 1789
CLOSE_WAIT 38
FIN_WAIT1 6
ESTABLISHED 94
SYN_RECV 3
LAST_ACK 3
LISTEN 23
[ayibang@db2 ~]$ ss -ant |awk '{S[$1]++}END{for (A in S) printf "%4s,%4s\n",S[A],A}'
8,LAST-ACK
3,SYN-RECV
292,ESTAB
1,State
4,FIN-WAIT-1
3,CLOSING
8,FIN-WAIT-2
6469,TIME-WAIT
41,CLOSE-WAIT
23,LISTEN
[root@centos5 ~]# awk -F: '$NF!~/^$/{SHELL[$NF]++}END{for(A in SHELL) printf "%16s:%s\n",A,SHELL[A]}' /etc/passwd
/sbin/shutdown:1
/bin/bash:5
/sbin/nologin:30
/sbin/halt:1
/bin/sync:1
[root@db2 logs]# awk '{IP[$1]++}END{for (A in IP) printf "%20s:%5s\n",A,IP[A]}' access_www.log |sort -rn|head
223.9.2.89: 37
223.68.131.168: 31
223.243.41.89: 1
223.240.233.91: 34
223.223.194.23: 50
223.223.194.215: 16
223.167.19.183: 65
223.166.112.132: 1
223.104.5.30: 69
223.104.5.2: 2
split($5,client,":")含義以下
ه內置函數split 先把第五個字段,以:爲分隔符,切割新的字段,保存成client數組,
IP[client[1]]++}END{for (i in IP){print IP[i],i}}'
以新的IP數組,client數組第一列爲新數組IP下標,最後作作求和,統計個數
split是函數 用小括號…………
[root@db2 ~]# netstat -ant|awk '/:80/{split($5,client,":");IP[client[1]]++}END{for (i in IP){print IP[i],i}}'|sort -rn |head
10 116.247.112.153
6 210.22.62.180
6 123.125.65.237
5 123.138.215.24
3 221.237.44.110
3 111.202.0.53
3 106.2.195.214
2 117.79.81.51
2 101.80.175.17
2 0.0.0.0
a文件
11 23
13 23
43 56
b文件
11 43
45 455
32 23
輸出結果以下
22 66
58 478
75 79
解答:
awk '{a[FNR]+=$1;b[FNR]+=$2} END{for(i in a){print a[i],b[i]}}' cc1.log cc2.log
awk '{n=FNR;a[n]+=$1;b[n]+=$2} END{for(i=1;i<=n;i++){print a[i],b[i]}}' cc1.log cc2.log
awk '{n=FNR;a[n]+=$1;b[n]+=$2; if(NR > n) print a[n],b[n]}' cc1.log cc2.log
awk '{n=FNR;a[n]+=$1;b[n]+=$2} NR > n {print a[n],b[n]}' cc1.log cc2.log
awk '{if(NR == FNR){a[NR]=$1;b[NR]=$2}else{print $1+a[FNR],$2+b[FNR]}}' cc1.log cc2.log
awk 'NR==FNR {a[NR]=$1;b[NR]=$2;next} {print $1+a[FNR],$2+b[FNR]}' cc1.log cc2.log
paste cc1.log cc2.log |awk '{print $1+$3,$2+$4}'
awk 'NR == FNR{a[i]=$1;b[i]=$2;i++} NR>FNR{print $1+a[j],$2+b[j];j++}' cc1.log cc2.log
20150418週末小題
原始數據:
17/Apr/2015:09:29:24 +0800
17/Apr/2015:09:30:26 +0800
17/Apr/2015:09:31:56 +0800
18/Apr/2015:09:34:12 +0800
18/Apr/2015:09:35:23 +0800
19/Apr/2015:09:23:34 +0800
19/Apr/2015:09:22:21 +0800
20/Apr/2015:09:45:22 +0800
指望結果:
2015-04-17 09:29:24+0800
2015-04-17 09:30:26+0800
2015-04-17 09:31:56+0800
2015-04-18 09:34:12+0800
2015-04-18 09:35:23+0800
2015-04-19 09:23:34+0800
2015-04-19 09:22:21+0800
2015-04-20 09:45:22+0800
解決實踐:來自運維21期悠久之翼 羣內分享
[root@web01 ~]# cat oldboy.txt
17/Apr/2015:09:29:24 +0800
17/Apr/2015:09:30:26 +0800
17/Apr/2015:09:31:56 +0800
18/Apr/2015:09:34:12 +0800
18/Apr/2015:09:35:23 +0800
19/Apr/2015:09:23:34 +0800
19/Apr/2015:09:22:21 +0800
20/Apr/2015:09:45:22 +0800
[root@web01 ~]# awk '{sub(/Apr/,"04");split($0,array,"[/: ]") ;printf("%s-%s-%s %s:%s:%s%s\n",array[3],array[2],array[1],array[4],array[5],array[6],array[7])}' oldboy.txt
2015-04-17 09:29:24+0800
2015-04-17 09:30:26+0800
2015-04-17 09:31:56+0800
2015-04-18 09:34:12+0800
2015-04-18 09:35:23+0800
2015-04-19 09:23:34+0800
2015-04-19 09:22:21+0800
2015-04-20 09:45:22+0800
1. sub函數
[root@nhserver1 10]# echo "a b c 2011-11-22 a:d" | awk 'sub(/-/,"",$4)'
a b c 201111-22 a:d
2. gsub函數
[root@nhserver1 10]# echo "a b c 2011-11-22 a:d" | awk 'gsub(/-/,"",$4)'
a b c 20111122 a:d
sub函數只實現第一個位置的替換,gsub函數實現全局的替換。
Split切割是第一列下表是1
[root@web01 ~]# sed -nr 's#(..)/(...)/(....):(..):(..):(..) (.*)#\3-\2-\1 \4:\5:\6\7#;s#Apr#04#p' oldboy.txt
2015-04-17 09:29:24+0800
2015-04-17 09:30:26+0800
2015-04-17 09:31:56+0800
2015-04-18 09:34:12+0800
2015-04-18 09:35:23+0800
2015-04-19 09:23:34+0800
2015-04-19 09:22:21+0800
2015-04-20 09:45:22+0800
. 是一個字符, s是替換 p打印
在編寫shell腳本的過程當中,咱們常常須要使用sed流編輯器和awk對文本文件進行處理。
sed 是一種在線編輯器,它一次處理一行內容。sed是非交互式的編輯器。它不會修改文件,除非使用shell重定向來保存結果。默認狀況下,全部的輸出行都被打印到屏幕上。
sed編輯器逐行處理文件(或輸入),並將結果發送到屏幕。具體過程以下:首先sed把當前正在處理的行保存在一個臨時緩存區中(也稱爲模式空間),而後處理臨時緩衝區中的行,完成後把該行發送到屏幕上。sed每處理完一行就將其從臨時緩衝區刪除,而後將下一行讀入,進行處理和顯示。處理完輸入文件的最後一行後,sed便結束運行。
前面說到sed不會修改文件,那麼如今咱們能夠知道是爲何了?是由於sed把每一行都存在臨時緩衝區中,對這個副本進行編輯,因此不會修改原文件。
補充知識:
在使用sed的過程當中,咱們常常會聽到「定址」,那麼什麼是「定址」呢?
定址用於決定對哪些行進行編輯。地址的形式能夠是數字、正則表達式、或兩者的結合。若是沒有指定地址,sed將處理輸入文件的全部行。
一、地址是一個數字,則表示行號;是「$"符號,則表示最後一行。
例如:
[plain] view plaincopy
二、只顯示指定行範圍的文件內容
例如:
[plain] view plaincopy
三、地址是逗號分隔的,那麼須要處理的地址是這兩行之間的範圍(包括這兩行在內)。範圍能夠用數字、正則表達式、或兩者的組合表示。
例如:
[plain] view plaincopy
sed命令告訴sed如何處理由地址指定的各輸入行,若是沒有指定地址則處理全部的輸入行。
一、sed命令
命令 |
功能 |
a\ |
在當前行後添加一行或多行。多行時除最後一行外,每行末尾需用「\」續行 |
c\ |
用此符號後的新文本替換當前行中的文本。多行時除最後一行外,每行末尾需用"\"續行 |
i\ |
在當前行以前插入文本。多行時除最後一行外,每行末尾需用"\"續行 |
d |
刪除行 |
h |
把模式空間裏的內容複製到暫存緩衝區 |
H |
把模式空間裏的內容追加到暫存緩衝區 |
g |
把暫存緩衝區裏的內容複製到模式空間,覆蓋原有的內容 |
G |
把暫存緩衝區的內容追加到模式空間裏,追加在原有內容的後面 |
l |
列出非打印字符 |
p |
打印行 |
n |
讀入下一輸入行,並從下一條命令而不是第一條命令開始對其的處理 |
q |
結束或退出sed |
r |
從文件中讀取輸入行 |
! |
對所選行之外的全部行應用命令 |
s |
用一個字符串替換另外一個 |
g |
在行內進行全局替換 |
w |
將所選的行寫入文件 |
x |
交換暫存緩衝區與模式空間的內容 |
y |
將字符替換爲另外一字符(不能對正則表達式使用y命令) |
二、sed選項
選項 |
功能 |
-e |
進行多項編輯,即對輸入行應用多條sed命令時使用 |
-n |
取消默認的輸出 |
-f |
指定sed腳本的文件名 |
與grep同樣,sed也支持特殊元字符,來進行模式查找、替換。不一樣的是,sed使用的正則表達式是括在斜槓線"/"之間的模式。
若是要把正則表達式分隔符"/"改成另外一個字符,好比o,只要在這個字符前加一個反斜線,在字符後跟上正則表達式,再跟上這個字符便可。
例如:
[plain] view plaincopy
經常使用的正則表達式以下:
元字符 |
功能 |
示例 |
^ |
行首定位符 |
/^my/ 匹配全部以my開頭的行 |
$ |
行尾定位符 |
/my$/ 匹配全部以my結尾的行 |
. |
匹配除換行符之外的單個字符 |
/m..y/ 匹配包含字母m,後跟兩個任意字符,再跟字母y的行 |
* |
匹配零個或多個前導字符 |
/my*/ 匹配包含字母m,後跟零個或多個y字母的行 |
[] |
匹配指定字符組內的任一字符 |
/[Mm]y/ 匹配包含My或my的行 |
[^] |
匹配不在指定字符組內的任一字符 |
/[^Mm]y/ 匹配包含y,但y以前的那個字符不是M或m的行 |
.. |
保存已匹配的字符 |
1,20s/youself/\1r/ 標記元字符之間的模式,並將其保存爲標籤1,以後可使用\1來引用它。最多能夠定義9個標籤,從左邊開始編號,最左邊的是第一個。此例中,對第1到第20行進行處理,you被保存爲標籤1,若是發現youself,則替換爲your。 |
& |
保存查找串以便在替換串中引用 |
s/my/**&**/ 符號&表明查找串。my將被替換爲**my** |
\< |
詞首定位符 |
/\<my/ 匹配包含以my開頭的單詞的行 |
\> |
詞尾定位符 |
/my\>/ 匹配包含以my結尾的單詞的行 |
x\{m\} |
連續m個x |
/9\{5\}/匹配包含連續5個9的行 |
x\{m,\} |
至少m個x |
/9\{5,\}/ 匹配包含至少連續5個9的行 |
x\{m,n\} |
至少m個,但不超過n個x |
/9\{5,7\}/ 匹配包含連續5到7個9的行 |
sed不向grep同樣,無論是否找到指定的模式,它的退出狀態都是0。只有當命令存在語法錯誤時,sed的退出狀態纔不是0。
一、p命令
命令p用於顯示模式空間的內容。默認狀況下,sed把輸入行打印在屏幕上,選項-n用於取消默認的打印操做。當選項-n和命令p同時出現時,sed可打印選定的內容。
例子:
[plain] view plaincopy
二、d命令
命令d用於刪除輸入行。sed先將輸入行從文件複製到模式空間裏,而後對該行執行sed命令,最後將模式空間裏的內容顯示在屏幕上。若是發出的是命令d,當前模式空間裏的輸入行會被刪除,不被顯示。
例子:
[plain] view plaincopy
三、s命令
例子:
[plain] view plaincopy
四、e選項
-e是編輯命令,用於sed執行多個編輯任務的狀況下。在下一行開始編輯前,全部的編輯動做將應用到模式緩衝區中的行上。
例子:
[plain] view plaincopy
五、r命令
r命令是讀命令。sed使用該命令將一個文本文件中的內容加到當前文件的特定位置上。
例如:
[plain] view plaincopy
六、w命令
例子:
[plain] view plaincopy
七、a\ 命令
a\ 命令是追加命令,追加將添加新文本到文件中當前行(即讀入模式緩衝區中的行)的後面。所追加的文本行位於sed命令的下方另起一行。若是要追加的內容超過一行,則每一行都必須以反斜線結束,最後一行除外。最後一行將以引號和文件名結束。
例子:
[plain] view plaincopy
八、i\ 命令
i\ 命令是在當前行的前面插入新的文本。
九、c\ 命令
sed使用該命令將已有文本修改爲新的文本。
十、n命令
sed使用該命令獲取輸入文件的下一行,並將其讀入到模式緩衝區中,任何sed命令都將應用到匹配行緊接着的下一行上。
例如:
[plain] view plaincopy
注:若是須要使用多條命令,或者須要在某個地址範圍內嵌套地址,就必須用花括號將命令括起來,每行只寫一條命令,或這用分號分割同一行中的多條命令。
十一、y命令
該命令與UNIX/Linux中的tr命令相似,字符按照一對一的方式從左到右進行轉換。例如,y/abc/ABC/將把全部小寫的a轉換成A,小寫的b轉換成B,小寫的c轉換成C。
例如:
[plain] view plaincopy
十二、q命令
q命令將致使sed程序退出,再也不進行其它的處理。
[plain] view plaincopy
1三、h命令和g命令
爲了更好說明這兩個命令,咱們先建立以下的文本文件:
[plain] view plaincopy
[plain] view plaincopy
補充知識點:sed特殊用法
[plain] view plaincopy
一、從文件讀入命令
[plain] view plaincopy
sed.sh文件內容:
[plain] view plaincopy
二、直接運行腳本 ./sed.sh /etc/passwd
[plain] view plaincopy
一、用sed 輸出本身的IP 地址
[plain] view plaincopy
二、在sed的命令行中引用shell變量時要使用雙引號,而不是一般所用的單引號。下面是一個根據name變量的內容來刪除named.conf文件中zone段的腳本:
name='zone\ "localhost"'
[plain] view plaincopy
三、保持和獲取:h命令和G命令
[plain] view plaincopy
在sed處理文件的時候,每一行都被保存在一個叫模式空間的臨時緩衝區中,除非行被刪除或者輸出被取消,不然全部被處理的行都將打印在屏幕上。接着模式空間被清空,並存入新的一行等待處理。在這個例子裏,匹配test的行被找到後,將存入模式空間,h命令將其複製並存入一個稱爲保持緩存區的特殊緩衝區內。第二條語句的意思是,當到達最後一行後,G命令取出保持緩衝區的行,而後把它放回模式空間中,且追加到如今已經存在於模式空間中的行的末尾。在這個例子中就是追加到最後一行。簡單來講,任何包含test的行都被複制並追加到該文件的末尾。
四、保持和互換:h命令和x命令
[plain] view plaincopy
互換模式空間和保持緩衝區的內容。也就是把包含test與check的行互換。
1,刪除文件每行的第一個字符。
[plain] view plaincopy
2,刪除文件每行的第二個字符。
[plain] view plaincopy
3,刪除文件每行的最後一個字符。
[plain] view plaincopy
4,刪除文件每行的倒數第二個字符。
[plain] view plaincopy
5,刪除文件每行的第二個單詞。
[plain] view plaincopy
6,刪除文件每行的倒數第二個單詞。
[plain] view plaincopy
7,刪除文件每行的最後一個單詞。
[plain] view plaincopy
8,交換每行的第一個字符和第二個字符。
[plain] view plaincopy
9,交換每行的第一個單詞和第二個單詞。
[plain] view plaincopy
10,交換每行的第一個單詞和最後一個單詞。
[plain] view plaincopy
11,刪除一個文件中全部的數字。
[plain] view plaincopy
12,刪除每行開頭的全部空格。
[plain] view plaincopy
13,用製表符替換文件中出現的全部空格。
[plain] view plaincopy
14,把全部大寫字母用括號()括起來。
[plain] view plaincopy
15,打印每行3次。
[plain] view plaincopy
16,隔行刪除。
[plain] view plaincopy
17,把文件從第22行到第33行復制到第44行後面。
[plain] view plaincopy
18,把文件從第22行到第33行移動到第44行後面。
[plain] view plaincopy
19,只顯示每行的第一個單詞。
[plain] view plaincopy
20,打印每行的第一個單詞和第三個單詞。
[plain] view plaincopy
21,將格式爲 mm/yy/dd 的日期格式換成 mm;yy;dd
[plain] view plaincopy
22, 逆向輸出
[plain] view plaincopy