正则表达式笔记
本章是学习shell的基础,本章学的越好,shell也就会学的越好。
在计算机科学中,正则表达式的含义是:它使用单个字符串来描述或匹配一系列符合某个句法规则的字符串。在许多文本编辑器或工具里,正则表达式通常用来检索和替换那些符合某个模式的文本内容。对系统管理员来说,正则表达式贯穿我们的日常运维工作当中,无论是查找某个文档,还是查询某个日志文件并分析其内容,都会用到正则表达式。
其实正则表达式只是一种思想、一种表示方法。只要工具支持这种方法,这个工具就可以处理正则表达式的字符串。常用的正则表达式有grep、sed、awk,它们都是针对文本的行来操作的。
11.1 grep/egrep工具的使用
grep命令的格式为:
grep [-cinvABC] ‘word’ filename,其常用选项表示如下:
-c:表示打印符合要求的行数
-i:表示忽略大小写
-n:表示输出符合要求的行及其行号
-v:表示打印不符合要求的行
-A:后跟一个数字(有无空格均可),如-A2表示打印符合要求的行以及下面两行
-B:后跟一个数字,如-B2表示打印符合要求的行以及上面两行
-C:后跟一个数字,如-C2表示打印符合要求的行以及上下各两行
实例1
命令:
grep -A2 'halt' /etc/passwd
解释:
打印包含halt的行以及这行下面的两行
注:在CentOS 7中,grep默认帮我们把匹配到的字符串标注了红色。用which命令查看grep,可以看到grep其实就是grep --color=auto,这个选项就是颜色表示。
实例2
命令:
grep -B2 'halt' /etc/passwd
解释:
打印包含halt的行以及这行上面的两行
实例3
命令:
grep -C2 'halt' /etc/passwd
解释:
打印包含halt的行以及这行的上下两行
11.1.1过滤出带有某个关键词的行,并输出行号
实例1
命令:
grep -n 'root' /etc/passwd
解释:
过滤出带有root的行,并输出行号
注:前面的数字显示为绿色,表示行号
11.1.2过滤出不带有某个关键词的行,并输出行号
实例1
命令:
grep -nv 'nologin' /etc/passwd
解释:
过滤出不带有nologin的行,并输出行号
11.1.3过滤出所有包含数字的行
实例1
命令:
grep '[0-9]' /etc/passwd
解释:
过滤出所有包含数字的行
注:只要有一个数字就算匹配到了
11.1.4过滤出所有不包含数字的行
实例1
命令:
grep -v '[0-9]' /etc/inittab
解释:
过滤出所有不包含数字的行
注:只要有一个数字就不显示
11.1.5过滤掉所有以#开头的行
实例1
命令:
grep -v '^#' /etc/sos.conf
解释:
过滤掉所有以#开头的行
注:这里面是含有空行的
11.1.6过滤掉所有空行和以#开头的行
实例1
命令:
grep -v '^#' /etc/passwd | grep -v '^$'
解释:
过滤掉所有空行和以#开头的行
注:在正则表达式中,^表示行的开始,$表示行的结尾,那么空行可以表示为^$。
实例2
命令:
grep '^[^a-zA-Z]' test.txt
解释:
以非字母开头
实例3
命令:
grep '[^a-zA-Z]' test.txt
解释:
过滤出带有非字母项的行
注:[]的作用,如果是数字就用[0-9]这样的形式(如果是[15],表示只含有1或者5),如果要过滤数字以及大小写字母,则要写成类似[0-9a-zA-Z]的形式。另外,^在中括号以外表示以中括号里面的东西开头;^在中括号以内表示除中括号里面的东西以外。
11.1.7 过滤出任意一个字符和重复字符
实例1
.表示任意一个字符
命令:
grep 'r.o' /etc/passwd
解释:
过滤出r和o之间有任意一个字符的行
实例2
*表示零个或多个*前面的字符
命令:
grep 'ooo*' /etc/passwd
解释:
过滤出至少带有2个o的行
实例3
.*表示零个或多个任意字符,空行也包括在内,它会把文件中的所有行都匹配到
命令:
grep '.*' /etc/passwd
解释:
过滤出文件中的所有行
实例4
命令:
grep '.*' /etc/passwd | wc -l
解释:
文件总共的行数,包括空行
11.1.8 指定要过滤出的字符出现次数
{}内部为数字,表示前面的字符要重复的次数。需要强调的是,{}左右都需要加上转义字符\。另外,{}还可以表示一个范围,具体格式为{n1,n2},其中n1<n2,表示重复n1到n2次前面的字符。n2可以为空,此时表示大于等于n1次。
实例1
命令:
# grep 'o\{2\}' /etc/passwd
解释:
过滤出o重复2次的行
实例2
命令:
grep 'o\{2,3\}' /etc/passwd
解释:
过滤出o重复2到3次的行
实例3
命令:
grep 'o\{2,\}' /etc/passwd
解释:
过滤出o重复2次以上的行
11.1.9 egrep的用法
过滤出一个或多个指定的字符
实例1
命令:
egrep 'o+' test.txt
egrep 'oo+' test.txt
egrep 'ooo+' test.txt
解释:
过滤出至少有1个o,2个o,3个o的行
注:egrep使用的+,表示匹配1个或多个+前面的字符,但是+是不支持被grep直接使用的。同时,{}也可以被egrep直接使用而不用加转义字符\。
实例2
命令:
egrep 'o{2}' /etc/passwd
grep 'o\{2\}' /etc/passwd
grep -E 'o{2}' /etc/passwd
解释:
过滤出o被重复2次的行
11.1.10 过滤出零个或一个指定的字符
实例1
egrep中的?表示重复0个或1个前面的字符
命令:
egrep 'o?' test.txt
解释:
过滤出不带o或者带有1个o的行
实例2
命令:
egrep 'ooo?' test.txt
解释:
过滤出带2个o或者3个o的行
11.1.11 过滤出字符串1或者字符串2
实例1
命令:
egrep 'aaa|111|ooo' test.txt
解释:
过滤出带有3个a或者3个1或者3个o的行
11.1.12 egrep中()的应用
实例1
命令:
egrep 'r(oo|at)o' test.txt
解释:
()表示一个整体,会把包含rooo或者rato的行过滤出来
实例2
命令:
egrep '(oo)+' test.txt
解释:
过滤出包含1个或者多个oo的行
11.2sed工具的使用
grep只能实现查找功能,而不能把查找的内容替换。vim可以查找和替换,但只限于在文本内部操作,而不能输出到屏幕上。sed和awk都是流式编辑器,是针对文档的行来操作的。
11.2.1 打印某行
sed命令的形式为:sed –n ‘n’p filename,单引号内的n是一个数字,表示第几行。-n的作用是只显示我们要打印的行,无关紧要的内容不显示,不加-n是打印所有行。
实例1
命令:
sed -n '2'p test.txt
解释:
打印第2行
实例2
命令:
sed -n '1,$'p test.txt
解释:
打印所有行
实例3
命令:
sed -n '2,3'p test.txt
解释:
打印2-3行的内容
11.2.2 打印包含某个字符串的行
实例1
命令:
sed -n '/root/'p test.txt
解释:
打印包含root的行
实例2
在grep中适用的特殊字符(如^$.*)同样也能在sed中使用
命令:
sed -n '/^1/'p test.txt
解释:
打印以1开头的字符串
实例3
命令:
sed -n '/in$/'p test.txt
解释:
打印以in结尾的行
实例4
命令:
sed -n '/r..o/'p test.txt
解释:
打印r和o之间有任意两个字符的行
实例5
命令:
sed -n '/ooo*/'p test.txt
解释:
打印至少含有2个o的行
实例6
sed命令加-e选项可以实现多个行为。
命令:
sed -e '1'p -e '/111/'p -n test.txt
解释:
先打印第1行再打印含有111的行
11.2.3 删除某些行
实例1
命令:
sed '1'd test.txt
解释:
删除第1行
实例2
命令:
sed '1,3'd test.txt
解释:
删除1-3行
实例3
命令:
sed '/oot/'d test.txt
解释:
删除带oot的行
注:d表示删除的动作,它不仅可以删除指定的单行和多行,还可以删除匹配某个字符的行,还可以删除从某一行开始到文档最后一行的所有行。不过,这个操作仅仅是在显示器屏幕上并不显示这些行而已,文档还好好的,并未对文档做真实的编辑。
11.2.4 替换字符或者字符串
参数s是替换动作,参数g是本行全局替换,如果不加g则只是替换本行出现的第1个
实例1
命令:
sed '1,2s/ot/to/g' test.txt
解释:
1,2行的ot全局替换成to
实例2
除了可以用/做分隔符,也可以用#和@。
命令:
sed 's#ot#to#g' test.txt
解释:
ot全局替换成to
实例3
命令:
sed 's/[0-9]//g' test.txt
解释:
删除所有的数字
注:[0-9]表示任意的数字,这里也可以写成[a-zA-Z]或者[0-9a-zA-Z]
实例4
命令:
sed 's/[a-zA-Z]//g' test.txt
解释:
删除字母
11.2.5 调换两个字符串的位置
实例1
命令:
sed 's/\(rot\)\(.*\)\(bash\)\3\2\1//' test.txt
解释:
调换rot和bash的位置
注:()在sed中式特殊符号,必须在前面加转义字符\,替换是写成类似\1、\2、\3的形式,()是把想要替换的字符打包成一个整体。
实例2
命令:
sed -r 's/(rot)(.*)(bash)/\3\2\1/' test.txt
解释:
加-r选项后()就可以不再使用转义字符表达式也更加清洗了。
实例3
命令:
sed 's/^.*$/123&/' test.txt
解释:
文件所有行开头加上123
实例4
命令:
sed 's/$/123&/' test.txt
解释:
结尾加上123
11.2.6 直接修改文件的内容(修改前先备份)
加-i选项,会对文档进行真实的修改
实例1
命令:
sed -i 's/ot/to/g' test.txt
解释:
真实修改文件的内容
11.3 awk工具的使用
11.3 awk工具的使用
awk也是流式编辑器,针对文档中的行来操作,一行一行地执行。
11.3.1 截取文档中的某个段
实例1
-F选项的作用是指定分隔符,如果不加-F选项,则以空格或者tab为分隔符。print为打印的动作,用来打印某个字段。$1为第一个字段,$2为第二个字段,依此类推。但$0比较特殊,它表示整行。
命令:
head -n2 test.txt | awk -F ':' '{print $1}'
解释:
用:做分隔符,打印test.txt前2行的第1段字符
实例2
命令:
head -n2 test.txt | awk -F ':' '{print $0}'
解释:
用:做分隔符,打印test.txt的前2行
注意awk的格式,-F后面紧跟单引号,单引号里面为分隔符。print动作要用{}括起来,否则会报错。
实例3
print可以打印自定义内容,但是自定义的内容要用“”括起来。
命令:
head -n2 test.txt | awk -F ':' '{print $1"#"$2"#"$3"#"$4}'
解释:
用:做分隔符,打印test.txt的前2行中第1,2,3,4部分,并且用#分开
11.3.2 匹配字符或者字符串
实例1
命令:
awk '/oo/' test.txt
解释:
打印test.txt中匹配oo的行
实例2
awk可以让某个段去匹配,~就是匹配的意思
命令:
awk -F ':' '$1 ~ /oo/' test.txt
实例:
用:做分隔符,打印第1段匹配oo的所有行
实例3
awk可以进行多次匹配
命令:
awk -F ':' '/root/ {print $1,$3} /test/ {print $1,$3}' test.txt
解释:
用:做分隔符,先匹配root再匹配test
11.3.3 条件操作符
awk可以用逻辑符号进行判断,判断符号有==(精确匹配)、>、>=、<、<=、!=。在和数字做比较时,数字加双引号表示字符,不加双引号表示数字。
实例1
命令:
awk –F ‘:’ ‘$3 == “0”’ /etc/passwd
解释:
/etc/passwd文件中,以冒号为分隔符,第3部分等于字符0
实例2
命令:
awk –F ‘:’ ‘$3 > 500’ /etc/passwd
解释:
把/etc/passwd中用户uid大于500的行打印出来
实例3
!=表示不匹配
命令:
awk –F ‘:’ ‘$7 != “sbin/nologin”’ /etc/passwd
解释:
把/etc/passwd中以冒号为分隔符第7部分不匹配/sbin/nologin的行打印出类
实例4
&&的用法
命令:
awk -F ':' '$3>"5"&&$3<"7"' /etc/passwd
解释:
把/etc/passwd中以冒号为分隔符分开的第3部分大于5小于7的部分打印出来
实例5
||的用法
命令:
awk -F ':' '$3>1000 || $7=="/bin/bash"' /etc/passwd
解释:
把/etc/passwd中以冒号为分隔符分开的第3部分大于1000或者第7部分等于/bin/bash的行打印出来
11.3.4 awk的内置变量
awk常用的变量有OFS、NF、NR。
实例1
OFS的用法
命令:
head -5 /etc/passwd | awk -F ':' '{OFS="#"} {print $1,$3,$4}'
解释:
/etc/passwd的前5行中,以冒号为分隔符,打印第1,3,4部分,并以#分开这3部分
实例2
OFS的高级用法
命令:
awk -F ':' '{OFS="#"} {if ($3>1000) {print $1,$2,$3,$4}}' /etc/passwd
解释:
在/etc/passwd中,打印第1,2,3,4部分,且第3部分大于1000,并以#分开这4部分
实例3
变量NF的具体用法(NF表示分隔符分隔后一共有多少段)
命令:
head -n3 /etc/passwd | awk -F ':' '{print NF}'
解释:
在/etc/passwd中,以冒号分割后一共有多少段
实例4
$NF表示最后一段的值
命令:
head -n3 /etc/passwd | awk -F ':' '{print $NF}'
解释:
在/etc/passwd中,以冒号分割后打印最后一个字段
实例5
变量NR的用法(NR表示行号)
命令:
awk 'NR>10' test.txt
用法:
打印行数大于10的所有行
实例6
NR和配合段一起使用
命令:
awk -F ':' 'NR<20 && $1 ~ /root/' /etc/passwd
解释:
在/etc/passwd中以冒号为分隔符,打印所有行数小于20且第1部分匹配root的行
11.3.5 awk中的数学运算
实例1
awk可以更改段值,就是把目标段改为自己设定的东西
命令:
head -n3 /etc/passwd | awk -F ':' '$1="root"'
解释:
在/etc/passwd的前3行中,以冒号为分隔符,将第1段改为root
实例2
awk可以对各个段的值进行数学运算
命令:
head -n2 /etc/passwd | awk -F ':' '{$7=$3+$4;print $0}'
解释:
在/etc/passwd的前2行中,以冒号为分隔符,将第7段改为第3段和第4段的和
实例3
awk可以计算某个段的总和
命令:
awk -F ':' '{(tot=tot+$3)}; END {print tot}' /etc/passwd
解释:
用:作为分隔符,把整个文档的第3个字段相加,求和
实例4
命令:
awk -F ':' '{if ($1=="root") {print $0}}' /etc/passwd
解释:
用:作为分隔符,打印第1字段等于root的行
总结:上面这些仅仅是正则表达式中最基本的内容,sed和awk并没有深入讲解,但足以满足日常工作需要。碰到复杂的,再研究便是。
友情链接:阿铭Linux