指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设grep指令会把含有范本样式的那一列显示出来。若不指定任何文件名称,或是所给予的文件名为"-",则grep指令会从标准输入设备读取数据。
格式:
#grep [OPTION]… PATTERN [FILE]…
grep常用参数:
[OPTIONS]:
-B num : 除了显示符合样式的那一行之外,并显示该行之前的num行内容。before
-A num :除了显示符合样式的那一行之外,并显示该行之前的num行内容。after
-C num:除了显示符合样式的那一行之外,并显示该行之前后num行内容。
-c :计算符合样式的列数
-d 动作: 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
-e :实现多个选项间的逻辑or关系.
-n :在显示符合样式的那一行之前,标出该行的列数编号,即显示行号;
-E :使用扩展的正则表达式 \egrep
-i :忽略字符大小写的差别
-o :只显示匹配的字符串部分
-v :显示不包含匹配文本的所有行
-V :显示版本信息
-s :不显示错误信息。
-w:强制'pattern'匹配部分只匹配整个单词。
练习:
///取出ifconfig命令中的所有ipv4地址。
[root@localhost Packages]# ifconfig|grep "inet "
inet 192.168.10.132 netmask 255.255.255.0 broadcast 192.168.10.255
inet 192.168.1.130 netmask 255.255.255.0 broadcast 192.168.1.255
inet 127.0.0.1 netmask 255.0.0.0
[root@localhost Packages]# ifconfig|grep "inet "|grep -Eo "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"
192.168.10.132
255.255.255.0
192.168.10.255
192.168.1.130
255.255.255.0
192.168.1.255
127.0.0.1
255.0.0.0
了解:
用法:#sed [option] … ‘script’ inputfile…
[option]:
-n:不输出模式空间内容到屏幕,即不自动打印。
-e:多点编辑。
-f:/PATH/SCRIPT_FILE:从指定文件中读取编辑脚本。
-r:支持使用扩展正则表达式。
-i.bak:备份原文件后,对原文件进行编辑修改。
注:i.bak是因为sed命令使用-i参数时不会询问,怕改错,有一定的危险性,因此-i.bak是在修改前先备份原文件,然后再修改该文件,一定程度上减少了出错风险。
inputfile:处理的文件
script:‘地址定界和编辑命令’;script是sed语言自身的语言脚本。
地址定界:
(1)不给地址:对全文进行处理。
(2)单地址:
#:指定的行,$:最后一行
/pattern/:被此处模式所能匹配到的每一行。支持正则表达式。
(3)地址范围:
#,#:如1,3:显示1到3行。
#,+#:如1,+6:显示1到7行(第一行再加6行)。
/pat1/,/pat2/:如/^ar1/,/^ar2/:匹配显示以ar1开头行~以ar2开头的行。支持正则表达式
#,/pat1/:如1,/^ar1:匹配显示从第一行至以"ar1"开头的行。
(4)~:步进
1~2:奇数行
2~2:偶数行
编辑命令:
注意—>多个编辑命令一起使用时,需要使用";"分隔。
编辑命令
d:删除模式空间匹配的行,并立即启用下一轮循环。即删除匹配的行。
p:打印当前模式空间内容,并追加到默认输出之后。
a\text:在指定行后面追加文件“text”。支持使用“\n”实现多行追加。
i\text:在指定行前面插入文本“text”。
c\text:替换行尾单行或多行文本。
w /path/somefile:保存模式匹配的行至指定文件。
r /path/somefile:读取指定文件的文本至模式空间中,匹配到行后。
=:为模式空间中的行打印行号。
!:模式空间中匹配行取反处理
s///:查找替换,支持使用其它分隔符,如s@@@,s###等。
替换标记:
s///:若一行内有多个重复内容,只替换第一个重复内容。
s///g:行内全局替换。
s///p:显示替换成功的行。
s///w /path/to/somefile:将替换成功的行保存至文件中。
高级编辑命令:“再添加一个保持空间,可以理解为模式空间的行缓存”
高级编辑命令:
P:打印模式空间开端至\n内容,并追加到默认输出之前。
h:把模式空间中的内容覆盖至保持空间中。
H:把模式空间中的内容追加至保持空间中。
g:从保持空间取出数据覆盖至模式空间。
G:从保持空间取出内容追加至模式空间。
n:读取匹配到的行的下一行追加至模式空间。
N:读取匹配到的行的下一行追加至模式空间。
d:删除模式空间中的行。
D: 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动。
如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环。
x:把模式空间中的内容与保持空间中的内容进行互换。
简单练习:
了解sed的-n参数与p编辑命令的意义
[root@localhost ~]# seq 1 5
1
2
3
4
5
[root@localhost ~]# seq 1 5|sed '2p'
1
2
2
3
4
5
[root@localhost ~]# seq 1 5|sed -n '2p'
2
///显示#seq 1 5 的奇数行和偶数行
[root@localhost ~]# seq 1 5|sed -n '1~2p'
1
3
5
[root@localhost ~]# seq 1 5|sed -n '2~2p'
2
4
//地址定界的使用
[root@localhost ~]# cat a.txt
cctv1.wfwofwof
aodiwa
erge
cctv1.mogm232
awdnaid
[root@localhost ~]# cat a.txt |sed -n '/^cctv1/p'
cctv1.wfwofwof
cctv1.mogm232
[root@localhost ~]# cat a.txt |sed -n '/^cctv1/,/^cctv1/p'
cctv1.wfwofwof
aodiwa
erge
cctv1.mogm232
[root@localhost ~]# cat a.txt |sed -n '2,/^cctv1/p'
aodiwa
erge
cctv1.mogm232
///地址定界+编辑命令的使用
[root@localhost ~]# seq 1 5
1
2
3
4
5
[root@localhost ~]# seq 1 5|sed '1,2d'
3
4
5
[root@localhost ~]# seq 1 5|sed '1,2a\ = = ='
1
= = =
2
= = =
3
4
5
[root@localhost ~]# seq 1 5|sed '1,2i\ = = ='
= = =
1
= = =
2
3
4
5
[root@localhost ~]# seq 1 5|sed '2c\ = = ='
1
= = =
3
4
5
[root@localhost ~]# seq 1 5|sed '1,2c\ = = ='
= = =
3
4
5
[root@localhost ~]# seq 1 5|sed -n '1,3w /root/ex.txt'
[root@localhost ~]# cat ex.txt
1
2
3
[root@localhost ~]# cat ex.txt
=======
[root@localhost ~]# seq 1 3|sed '1,2r /root/ex.txt'
1
=======
2
=======
3
[root@localhost ~]# cat ex.txt
=======
wwafr
212
[root@localhost ~]# cat ex.txt|sed '='
1
=======
2
wwafr
3
212
[root@localhost ~]# seq 1 3
1
2
3
[root@localhost ~]# seq 1 3 |sed -n '1,2!p'
3
复杂练习:
'1.在/etc/sysconfig/grub文件中的quiet和结尾"冒号"之间加上net.ifnames=0'
[root@localhost ~]# cat /etc/sysconfig/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
[root@localhost ~]# sed -nr '/GRUB_CMDLINE_LINUX/s/(")$/ net.ifnames=0\1/p' /etc/sysconfig/grub
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet net.ifnames=0"
[root@localhost ~]# sed -nr '/GRUB_CMDLINE_LINUX/s/(quiet)"$/\1 net.ifname=0"/p' /etc/sysconfig/grub
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet net.ifname=0"
'2.取出ifconfig命令中的指定地址'
[root@localhost ~]# ifconfig|sed -n '/inet /p'
inet 192.168.10.132 netmask 255.255.255.0 broadcast 192.168.10.255
inet 192.168.1.130 netmask 255.255.255.0 broadcast 192.168.1.255
inet 127.0.0.1 netmask 255.0.0.0
[root@localhost ~]# ifconfig|sed -n '/inet /p'|sed -nr 's/inet (.*)netmask (.*)broadcast (.*)/\1/p'
192.168.10.132
192.168.1.130
[root@localhost ~]# ifconfig|sed -n '/inet /p'|sed -nr 's/inet (.*)netmask (.*)broadcast (.*)/\3/p'
192.168.10.255
192.168.1.255
'3.在aa.txt文本中以a2为首的行后添加"path=\/root\/example"字段。'
[root@localhost ~]# cat aa.txt
a1
a2
a3
[root@localhost ~]# sed -nr '/^a2/s/(.*)/\1 path=\/root\/example /p' /root/aa.txt
a2 path=/root/example
# sed -nr '/^a2/s/a2/& path=\/root\/example /p' /root/aa.txt //"&"代表前面匹配的字符串
a2 path=/root/example
'4.显示aa.txt文本中的空行,及其行号。'
[root@localhost ~]# cat aa.txt
a1
a2
a3
[root@localhost ~]# sed -n -e '/^$/p' -e '/^$/=' /root/aa.txt
2
'5.将a.conf文本中的NAME=80的#去掉,将至 行的#去掉。'
[root@localhost ~]# cat a.conf
#Name=80
#AIHI
#NIIEFSJ
#
#SRGTFHTFH
#SRHTTRT
#
[root@localhost ~]#sed -nr '/^#Name=/s/#//p' /root/a.conf
Name=80
[root@localhost ~]#sed -nr '/^#
<Vir *:80>
SRGTFHTFH
SRHTTRT
</Vir>
[root@localhost ~]# sed -r -i.bak -e '/^#Name=/s/#//' -e '/^#
[root@localhost ~]# ls
a.conf a.conf.bak
[root@localhost ~]# cat a.conf
Name=80
#AIHI
#NIIEFSJ
<Vir *:80>
SRGTFHTFH
SRHTTRT
</Vir>
///错误的例子:该修改会将显示的输出结果作为最终判别
[root@localhost ~]# sed -nr -i.bak1 -e '/^#Name=/s/#//p' -e '/^#
[root@localhost ~]# ls
a.conf a.conf.bak1
[root@localhost ~]# cat a.conf
Name=80
<Vir *:80>
SRGTFHTFH
SRHTTRT
</Vir>
'6.将ex.txt文本中第一行的第一个s替换为S,将第二行的所有s替换为S'
[root@localhost ~]# cat ex.txt
WWW s WWWsss
WWW s WWWsss
[root@localhost ~]# sed -nr -e '1s/s/S/p' -e '2s/s/S/gp' /root/ex.txt
WWW S WWWsss
WWW S WWWSSS
'7.取下列路径的目录名和基名;'
root@localhost ~]# echo "/etc/sysconfig/network/"|sed -nr 's/(.*\/)([^/]+\/?$)/\1/p'
/etc/sysconfig/
root@localhost ~]# echo "/etc/sysconfig/network/"|sed -nr 's/(.*\/)([^/]+\/?$)/\2/p'
network/
[root@localhost ~]# echo "/etc/sysconfig/network"|sed -nr 's/(.*\/)([^/]+\/?$)/\1/p'
/etc/sysconfig/
[root@localhost ~]# echo "/etc/sysconfig/network"|sed -nr 's/(.*\/)([^/]+\/?$)/\2/p'
network
'8.将奇数行和偶数行合并显示;'
[root@localhost ~]# seq 1 10|sed -n 'N;s/\n/ /p'
1 2
3 4
5 6
7 8
9 10
[root@localhost ~]# seq 1 10|xargs -n2
1 2
3 4
5 6
7 8
9 10
'9.删除文本内容,只保留最后一行。'
#seq 1 5 |sed 'N;D'
'10.统计/dev/sr0/Packages目录下的rpm包的架构类型(倒数第二列),并统计各类型有多少rpm包。'
[root@localhost Packages]# ls *.rpm
.....
zziplib-devel-0.13.62-5.el7.i686.rpm
zziplib-devel-0.13.62-5.el7.x86_64.rpm
zziplib-utils-0.13.62-5.el7.x86_64.rpm
[root@localhost Packages]# ls *.rpm |sed -nr 's/(.*)\.(.*)\.rpm$/\2/p'|sort -n|uniq -c
2223 i686
3117 noarch
4571 x86_64
[root@localhost Packages]# ls *.rpm|sed -r 's/(.*)\.rpm$/\1/'|sed -r 's/(.*)\.([^.]+)/\2/'|sort -n |uniq -c
2223 i686
3117 noarch
4571 x86_64
[root@localhost Packages]# ls *.rpm|sed -r 's/.*\.([^.]+)\.rpm$/\1/'|sort -n |uniq -c
2223 i686
3117 noarch
4571 x86_64
[root@localhost Packages]# ls *.rpm|rev|cut -d"." -f 2|rev |sort -n|uniq -c
2223 i686
3117 noarch
4571 x86_64
'11.使用sed将/etc/fstab文件中不以#开头的行添加#'
[root@localhost ex]# sed -nr '/^#/!p' /etc/fstab |sed -r 's/(.*)/#\1/'
#UUID=ac88f5f1-a119-4eeb-a044-61bd116c5444 / xfs defaults 0 0
#UUID=04be53f7-9583-497d-8668-dc0e694be23b /boot xfs defaults 0 0
#UUID=6bcd3943-2a8d-4117-83e6-4b11afc2640a /data xfs defaults 0 0
#UUID=70c96873-6113-4b55-91d0-9d70a890d1d5 swap swap defaults 0 0
#/dev/sr0 /mnt/cdrom iso9660 defaults 0 0
[root@localhost ex]# sed -nr '/^[^#]/s/(.*)/#\1/p' /etc/fstab
#UUID=ac88f5f1-a119-4eeb-a044-61bd116c5444 / xfs defaults 0 0
#UUID=04be53f7-9583-497d-8668-dc0e694be23b /boot xfs defaults 0 0
#UUID=6bcd3943-2a8d-4117-83e6-4b11afc2640a /data xfs defaults 0 0
#UUID=70c96873-6113-4b55-91d0-9d70a890d1d5 swap swap defaults 0 0
#/dev/sr0 /mnt/cdrom iso9660 defaults 0 0
简介
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
awk工作原理
#awk [options] 'BEGIN{action;...} pattern{action;..} END{action;...}' file..
第一步:
执行BEGIN{action;..}语句块中的语句。
第二步:
从文件或标准输入(stdin)读取一行,然后执行pattern{action;..}语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,知道文件全部被读取完毕。
第三步:
当读至输入流末尾时,执行END{action;..}语句块。
BEGIN、END、pattern语句块:
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
END语句块在awk从输入流中读取完所有的行之后再被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。
pattern语句块中的通用命令时最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print},即打印每一个读取到的行,awk读取的每一行都会执行该语句块。
在awk中分隔符、域和记录:
1.awk默认的分隔符为空白符,当以空白符做分隔符时,不用指定-F分隔符,且自动"去重"空白符。空白符包括空格、TAB键、回车、换行...等;
2.awk执行时,由分隔符分隔的字段(域)标记$1,$2,...$n称为域标记。$0为所有域。注意:和shell中变量$符含义不同。
3.省略action,则默认执行print $0的操作。
4.行row:也称记录record(在awk中, 称为记录更合适些,一般来说,记录=行)
5.列:也称域field,字段,属性
注意:在下列中,当以":"做分隔符时,cc和dd算是$3域的,不在一行,因此在这种情况下,记录更为合适。
调用awk方式:
'1.命令行方式:'
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键"。
#awk 'BEGIN {action} /pattern/{action} END {action}' input-file
awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
'2.shell脚本方式:'
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
'3.将所有的awk命令插入一个单独文件,然后调用:'
#awk -f awk-program-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本'program',input-file(s)跟上面的是一样的。
#awk [options] ‘program’ file…
#awk [options] ‘BEGIN{action;…} pattern{action;…} END{action;…}’ file…
'[options]':
-F:指明输入时用到的字段分隔符。
-v var=value :自定义变量。
-f programfile:加载programfile文件中的awk的program。
program:pattern{action statements;...}
'pattern'和'action':
pattern决定了动作语句何时触发及触发事件。
BEGIN,pattern,END
action statements是对数据进行处理,放在{}内指明。
print,printf,运算符,条件语句等。
'pattern'
pattern:根据pattern条件,过滤匹配的行,再做处理。
(1)如果未指定:空模式,匹配每一行。
(2)/pattern/:仅处理能够模式匹配到的行,需要用/ /括起来。
#awk '/^UUID/{print $1}' /etc/fstab
#awk '!/^UUID/{print $1}' /etc/fstab
(3)pattern:关系表达式,结果为“真”,才会被处理。
真:结果为非0值,非空字符串。
假:结果为0值或为空字符串。
(4)line ranges:行范围
/part1/,/part2/:不支持直接给出数字格式。
(5)BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次。
END{}:仅在文本处理完成之后执行一次。
#awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd
#awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
#awk -F: '/^root\>/{print $1,$5}' /etc/passwd
#awk -F: '$3==0{print $1}' /etc/passwd
#awk -F: '($3==0){print $1}' /etc/passwd
#awk -F: '!($3<=500){print $1}' /etc/passwd
#awk -F: 'BEGIN{print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd
#awk -F: '{print "USER USERID";print $1":"$3;print "end file"}' /etc/passwd
'action'
常用的action分类:
(1)算术,比较表达式等;
(2)if,while等语句;
(3)组合语句;
(4)print,printf,system命令;
print命令
print格式:{print item1,item2...}
要点:
(1):逗号做分隔符(显示的输出分隔符为空白符)。
(2):指定输出分隔符{item1"输出分隔符"item2}
(3):输出的各item可以是字符串、数值、当前记录的字段、变量或awk表达式。
(4):若省略item,相当于{print $0}
#awk -F: '{print}' /etc/passwd
#awk -F: '{print $1"--"$3}' /etc/passwd
#awk '{print "hello,awk"}'
printf命令:
格式化输出:{printf "format",item1,item2,...}
(1):必须制定format格式符;
(2):不会自动换行,需要显示给出换行控制符,\n。
(3):format中需要分别为后面每个item指定格式符。
格式符:format与item一一对应。(只有一对一)
%c:显示为字符的ASCII码。
%d,%i:显示为十进制整数。
%e,%E:显示为科学计数法数值。
%f:显示为浮点数。
%g,%G:以科学计数法或浮点形式显示数值。
%s:显示字符串。
%u:无符号整数。
%%:显示%自身
修饰符:
'±#.#:第一个#(数字)控制显示的宽度;第二个#(数字)表示小数点后精度,如"3.1",即%3.1f。'
-:左对齐(默认右对齐),%-15.2s。
+:显示数值的正负符号,%+d。
#awk -F: '{printf "%s\n",$1}' /etc/passwd
#awk -F: '{printf "%s %s\n",$1,$3}' /etc/passwd
#awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
#awk -F: '{printf "Username:%s,UID:%d\n",$1,$3}' /etc/passwd
system命令:awk中调用shell命令
注意:空格是awk中的字符串连接符。如果system中需要使用awk中的变量,可以使用空格分隔;或者说除了awk的变量外,其他一律用""引用起来。
#awk BEGIN'{system("homtname")}'
#awk BEGIN'{score=100;system("echo your socre is " score)}'
#df -h|awk -F% '/^\/dev\/sd/{print $1}'|awk '{if($NF>20)system("date")}'
awk 程序的(‘program’)通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成。其中,program通常是被单引号或双引号中,使用awk语言编辑。
变量:内置变量和自定义变量
内置变量:
FS:输入字段分隔符,默认为空白字符。
#awk -v FS=':' '{print $1,FS,$3}' /etc/passwd //该例中':'即做输入字段分隔符又做输出字段分隔符。
#awk -F: '{print $1,$3,$5}' /etc/passwd //-F指定输入分隔符,或-v FS=''通过变量指定输入分隔符。
OFS:输出字段分隔符,默认为空白字符。
#awk -v FS=':' -v OFS="$" '{print $1,$3,$5}' /etc/passwd
RS:输入记录分隔符,指定输入时的换行符。
#awk -v RS=':' '{print}' /etc/passwd
ORS:指定输出记录分隔符,输出时用指定符号代替换行符。
#awk -v RS='\n' -v ORS='###' '{print}' /etc/passwd
NF:字段数量,列数。
#awk -F: '{print NF}' /etc/passwd
#awk -F: '{print$(NF-1)}' /etc/passwd
NR:记录号,可以理解为行号。
#awk '{print NR}' /etc/fstab
#awk 'END{print NR}' /etc/passwd
FNR:各文件分别计数,记录号。
#awk '{print FNR}' /etc/fstab /etc/passwd
FILENAME:当前文件名
#awk '{print FILENAME}' /etc/passwd
ARGC:命令行参数的个数
#awk '{print ARGC}' /etc/fstab /etc/inittab
ARGC:数组,保存的是命令行所给定的各参数
#awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/passwd
#awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/passwd
自定义变量(区分字符大小写)
(1)-v var=value
(2)在program中直接定义
#awk -v test="hello word" '{print test}' /etc/fstab
#awk -v test="hello word" 'BEGIN{print test}' /etc/fstab
#awk 'BEGIN{test="hello,word";print test}'
#awk -F: '{test="username";print test":"$1}' /etc/passwd
算术操作符:x+y,x-y,x*y,x/y,x^y,x%y。
-x:转换为负数
+x:转换为数值
字符串操作符:没有符号的操作符,字符串连接。
赋值操作符:=,+=,-=,*=,/=,%=,^=,++,--。
#awk 'BEGIN{i=0;print ++i,i}'
#awk 'BEGIN{i=0;print i++,i}'
比较操作符:==,!=,>,>=,<,<=。
#awk -F: '($3>1000){print $1,$3}' /etc/passwd
模式匹配符:
~:左边是否和右边匹配包含。包含
!~:是否不匹配。不包含
#awk -F: '$0 ~ /root/{print $1}' /etc/passwd
#awk -F: '$0 ~ "^root"{print $1}' /etc/passwd
#awk '$0 !~ /root/' /etc/passwd
#awk -F: '$3==0' /etc/passwd
逻辑操作符:与&&,或||,非!
#awk -F: '$3>900 && $3<1000{print $1,$3}' /etc/passwd
#awk -F: '$3>900 || $3<1000{print $1,$3}' /etc/passwd
#awk -F: '!($3==0){print $1}' /etc/passwd
#awk -F: '!($3<=500){print $1}' /etc/passwd
函数调用:function_name(arg1,arg2,...)
条件表达式(三目表达式):
selector?if-true-expression:if-false-expression
如果selector条件判断为真,则执行if-ture--,如果条件判断为假,则执行if-false--
#awk -F: '{$3 >=1000?usertype="Common user":usertype="Sysadmin";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
语法:
{statements;...}组合语句----->即'{语法}'
if(condition){statement;...}
if(condition){statement;...} else{statements;..}
while(conditon){statments;..}
do{statements;..}while(condition)
for(expr1;expr2;expr3){statements;..}
break
continue
delete array[index]
delete array
exit
'----------------------------------'
'if、if-else、if-else if-else;
使用场景:-->对awk取得的整行或某个字段做条件判断'
例:
[root@localhost ~]# awk -F: '{if($3>=1000){print $1,$3}}' /etc/passwd
[root@localhost ~]# awk -F: '{if($NF == "/bin/bash"){print $1,$NF}}' /etc/passwd
[root@localhost ~]# awk -F: '{if($3>=1000){printf "commond user:%s\n",$1} else{printf "root or sysuser:%s\n",$1}}' /etc/passwd
[root@localhost ~]# df -h|awk -F% '/^\/dev\/sd/{print $1}'|awk '($NF>20){print $1,$5}'
[root@localhost ~]# df -h|awk -F% '/^\/dev\/sd/{print $1}'|awk '{if($NF>20){print $1,$5}}'
[root@localhost ~]# awk 'BEGIN{test=100;if(test>90){print "very good"} else if(test>60){print "good"} else{print "no pass"}}'
'while循环
条件“真”,进入循环;条件“假”,退出循环。
使用场景:-->对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用。
语法:while(conditon){statments;..}'
例:
[root@localhost ex]# awk '/^[[:space:]]*linux16/' /etc/grub2.cfg
linux16 /vmlinuz-3.10.0-862.el7.x86_64 root=UUID=ac88f5f1-a119-4eeb-a044-61bd116c5444 ro crashkernel=auto rhgb quiet LANG=en_US.UTF-8
linux16 /vmlinuz-0-rescue-e1b76d47681143e68f3a92f6c41b113e root=UUID=ac88f5f1-a119-4eeb-a044-61bd116c5444 ro crashkernel=auto rhgb quiet
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i;i++}}' /etc/grub2.cfg
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)<=10) {print $i,length($i)};i++}}' /etc/grub2.cfg
'do-while循环
意义:-->无论真假,至少执行一次循环体
语法:do{statements;..}while(condition)'
例:
# awk 'BEGIN{total=0;i=0;do{total+=i;i++}while(i<=100);print total}'
'for循环
语法:for(expr1;expr2;expr3){statements;..}
常见用法:for(变量赋值;变量使用场景;迭代过程){statements;..}
特殊用法:遍历数组中的元素-->for(var in aray){statements;..}'
例:
# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i}}' /etc/grub2.cfg
# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
# awk 'BEGIN{for(i=1;i<=1000;i++);sum+=i;{print sum}}'
# awk 'BEGIN{for(i=1;i<=1000;i++)sum+=i;{print sum}}'
# awk 'BEGIN{for(i=1;i<=1000;i++){sum+=i;print sum}}'
'switch语句
语法:switch(expression){case value1 or /REGEXP1/:statement1;case value2 or /REGEXP2/:statement2;..;default:statement}'
'break和continue'
例:
[root@localhost ex]# awk 'BEGIN{sum=0;for(i=1;i<=10;i++){if(i==5)break;sum+=i}print sum}'
[root@localhost ex]# awk 'BEGIN{sum=0;for(i=1;i<=10;i++){if(i==5)contiue;sum+=i}print sum}'
关联数组:array[index-expressio]
index-pression:
awk数组练习:
[root@localhost ex]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}'
Tuesday
Monday
[root@localhost ex]# awk '{print $1}' /var/log/httpd/access_log|uniq -c
104 192.168.1.1
11 10.11.2.3
6 221.32.4.1
15 123.4.2.6
11 13.5.7.9
10 125.234.5.8
[root@localhost ex]# awk '/^[0-9]/{ip[$1]++}END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log
15 123.4.2.6
11 13.5.7.9
104 192.168.1.1
6 221.32.4.1
10 125.234.5.8
11 10.11.2.3
[root@localhost ex]# netstat -tan|awk '/^tcp/{state[$NF]++}END{for(i in state){print state[i],i}}'
10 LISTEN
2 ESTABLISHED
[root@localhost ex]# awk '/^[0-9]/{ip[$1]++}END{for(i in ip){print i}}' /var/log/httpd/access_log|while read ip;do iptables -A INPUT -s $ip -j REJECT;done
[root@localhost ex]# iptables -vnL
Chain INPUT (policy ACCEPT 26 packets, 1584 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- * * 123.4.2.6 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 13.5.7.9 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 192.168.1.1 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 221.32.4.1 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 125.234.5.8 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 10.11.2.3 0.0.0.0/0 reject-with icmp-port-unreachable
'统计/etc/passwd中以:为分隔符,每个字符串出现的次数'
[root@localhost ex]# awk -F: '{for(i=1;i<=NF;i++){word[$i]++}}END{for(j in word)print j,word[j]}' /etc/passwd
'数值处理:'
- rand():返回0和1之间的一个随机数。
- 例:#awk 'BEGIN{rand();for(i=1;i<=10;i++)print int(rand()*100)}'
'字符串处理:'
length([s]):返回指定字符串"[s]"的长度。
sub(r,s,[t]):对t字符串进行搜索,r表示为模式匹配的内容,并将第一个匹配的内容替换为s。
- #echo "2008:08:08: 08:08:08"|awk 'sub(/:/,"-",$0)'
gsub(r,s,[t]):对t字符串进行搜索,r表示为模式匹配的内容,并全部替换为s所表示的内容。
- #echo "2008:08:08: 08:08:08"|awk 'sub(/:/,"-",$0)'
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,...
- #netstat -tan |awk '/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){printi,count[i]}}'
- #head -n1 /etc/passwd|awk '{split($0,arr,":")}END{for(i in arr){print i,arr[i]}}'
'自定义函数:'
格式:
function name(parameter,parameter,..)
{
statements
return expression
}
例:#cat fun1.awk
function max(v1,v2)
{
v1>v2?var=v1:var=v2
return var
}
BEGIN{a=3;b=2;print max(a,b)}
#awk -f fun1.awk
#cat fun2.awk
function max(v1,v2)
{
v1>v2?var=v1:var=v2
return var
}
BEGIN{print max(a,b)}
#awk -v a=100 -v b=200 -f fun2.awk
将awk程序写成脚本,直接调用或执行。
例:
#ca f1.awk
{if($3>=1000)print $1,$3}
#awk -F: -f f1.awk /etc/passwd
#cat f2.awk
#!/bin/awk -f
#this is a awk script
{if($3>=1000)print $1,$3}
#chmod +x f2.awk
#f2.awk -F: /etc/passwd
向awk脚本传递参数
格式:awkfile var=value var2=value2..Inputfile
注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数。
例:
#cat test.awk
#!/bin/awk -f
{if($3>=min && $3<=max)print $1,$3}
#chmod +x test.awk
#./test.awk -F: min=100 max=200 /etc/passwd(√)
#./test.awk -F: -v min=100 -v max=200 /etc/passwd(√)
练习:
[root@localhost ~]# awk -F: '($3>1000){print $1,$3}' /etc/passwd
app 1001
appq 1002
rooter 1003
bash 1004
[root@localhost ~]# awk -F: '$3>900 && $3<1000{print $1,$3}' /etc/passwd
polkitd 999
libstoragemgmt 998
chrony 997
appd 996