目录
一、介绍:
正则表达式适用于描述字符排列和匹配模式的一种语法规则,他主要用于字符串的分割、匹配、查找及替换等操作
即正则表达式是一种文本模式,改模式描述在搜索文本是要匹配的一个或多个字符串
这种枯燥的概念难理解,其实,正则表达式是用来匹配文件中的字符串的方法。
它会先把整个文本分成一行一行的字符串,然后从每行字符串中搜索是否有符合正则表达式规则的字符串,如果有则匹配成功,如果没则失败。
注:正则表达式和通配符的区别(正则表达式用来在文件中匹配符合条件的字符串,通配符用来匹配符合条件的文件名)。其实这种区别只在 Shell 中适用,因为用来在文件中搜索字符串的命令,如 grep、awk、sed、vi 等可以支持正则表达式,而在系统中搜索文件的命令,如 ls、find、cp 等不支持正则表达式,所以只能使用 Shell 自己的通配符来进行匹配了。
在正则表达式中,我们把用于匹配的特殊符号又称作元字符。在shell中,元字 符又分为基础元字符(BRE)和扩展元字符(ERE)。
二、表达式的书写符合对应的含义
下面就是正则表达式的符号,每个符号表示什么意思:
2.1、基础元字符
基础元字符 | |
元字符 | 作用 |
* | 匹配前面的一个字符或子表达式0次或任意多次。如:a*hello匹配所有0个或多个a后,紧跟hello的行。即hello前面可以有任意多个a。 |
. | 匹配除换行符和回车符(“\n”和"\r")外的任意一个字符。例如:l..e匹配包含一个l,后跟两个任意字符,然后跟一个e的行。 |
.* | 表示匹配任意长度字符串 |
^ | 匹配行首。例如,^hello 会匹配以 hello 开头的行。 |
$ | 匹配行尾。例如,hello$ 会匹配以 hello 结尾的行 |
^$ | 匹配空行 |
[] | 匹配中括号中指定的任意一个字符,而且只匹配一个字符。例如[aoeiu]匹配任意一个元音字母, [0-9] 匹配任意一位数字,[a-z][0-9] 匹配由小写字母和一位数字构成的两位字符,[a-zA-Z] 匹配任意一位英文字母 |
[^] | 匹配除中括号中的字符以外的任意一个字符。例如,[^0-9] 匹配任意一位非数字字符,[^a-z] 匹配任意一位非小写字母, 注意:可以用^标记做[]内的前缀,表示除[]内的字符以外的任意一个字符。比如:搜索oo前没有g的字符串的行,应用 '[^g]oo' 作搜索字符串。^符号如果出现在[]的起始位置表示否定,但是在[]的其他位置是普通字符。[^ab^c] 匹配除了a、b、^、c以外的任意单个字符。 |
\ | 转义符,用于取消特殊符号的含义,使该特殊字符成为普通字符。例如:^\.[0-9][0-9]表示匹配以一个句点和两个数字开始。 |
\{n\} | 表示其前面的字符出现 n 次。例如,[0-9]\{4\} 匹配4位数字,1[35-9][0-9]\{9\} 匹配手机号码。 |
\{n,\} | 表示其前面的字符出现不少于 n 次。例如,[0-9]\{2,\} 匹配两位及以上的数字 |
\{n,m\} | 表示其前面的字符至少出现 n 次,最多出现 m 次。例如,[a-z]\{6,8\} 匹配 6〜8 位的小写字母 |
\< \> | 匹配词(word)的开始(\<)和结束(\>)。例如正则表达式\能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。 |
除了上面的基础元字符,还有扩展的表达式
熟悉正则表达式的人应该很疑惑,在正则表达式中应该还可以支持一些元字符,比如"+"、"?"、"|"、"()"。
其实 Linux 是支持这些元字符的,只是 grep 命令默认不支持而已,因为grep把这些扩展元字符看成是普通符号,如果要想支持这些元字符,则可以使用 egrep 或 grep -E 命令。所以我们又把这些元字符称作扩展元字符。
如果査询egrep 命令的帮助,对 egrep 的说明就是和 grep -E 一样的命令,
2.2、Shell 中支持的扩展元字符。
扩展元字符 | 描述 |
+ | 匹配前面的一个字符或子表达式1次或任意多次。 如“go+gle”会匹配“gogle” “google”或“gooogle”。当然,如果“o”有更多个,则也能匹配。 egrep “go+gle” filename或grep -E “go+gel” filename |
? | 匹配前面的一个字符或子表达式零次或一次。例如:如 “colou?r” 可以匹配 “colour” 或 “color” |
| | 表示或。如“was|his”既会匹配包含“was”的行,或匹配包含“his”的行 |
() | 将括号里的内容看成是一个整体。可以理解为由多个单个字符组成的大字符。 如“(dog)+”会匹配“dog” “dogdog” “dogdogdog”等,因为被()包含的字符会被当成一个整体。但 “hello(world|earth)” 会匹配 “hello world” 及 “hello earth” |
注:"+"、"?"、"|"、"()"、"{}"等扩展元字符egrep命令或grep -E是支持的。grep命令在不加-E选项的情况下可以按如下格式写:"\+"、"\?"、"\|"、"\(\)"、"\{\
三、示范案例
下面举例来说明这些元字符的作用。我们已经学习过的 grep 命令支持正则表达式,所以下面的练习都需要利用 grep 命令来演示。在使用 grep 命令开始练习之前,建议大家在 ~/.bashrc 文件中建立这个别名,如下:
[root@localhost ~]# vi /root/.bashrc
alias grep='grep --color=auto'
执行source命令使修改生效
[root@localhost ~]#source /root/.bashrc
这样,grep 命令所匹配的字符都会使用颜色提示,更加容易理解正则表达式所具体匹配的字符串。
先创建内容: cat test.txt
Mr. Li Ming said:
he was the most honest man in LampBrother.
123despise him.
But since Mr. shen Chao came,
he never saaaid those words.
5555nice
because,actuaaaally,
Mr. Shen Chao is the most honest man
Later,Mr. Li ming soid his hot body.
3.1、”*“的使用
*:匹配前一个字符0次或任意多次,注意的是这个”*“不是通配符中的”*“含义不同,他代表前一个字符重复0次或任意多次,如何
a*并不是a后面的任意字符,而且可以匹配所有内容,包括空白行,
如:grep "a*" test.txt
注意这个之匹配前一个字符的如下吗aaa*,就表示前面至少要有两个a
grep "aaa*" test.txt
3.2、"."的使用
“.”:匹配除换行符和回车符的任意一个字符正则表达式“*”自能匹配一个字符,这个字符可以是任意字符
如:grep "s..d" test.txt
可以查看到s与d之间有两个“.” 表示s与d之间可以有任意两个字符
3.3、".*"结合的使用
与.结合表示任意长度的字符 .
如:grep "s.*d" test.txt
3.4、"^"、 "$"
"^":表示匹配行首,就是以什么字符开头,"$":表示以什么为结尾 ,比如^M:就是一M为开头的行
grep '^M' test.txt 、 grep 'n$' test.txt
这两个也可以结合表示匹配空行 ^$表示
grep -n "^$" test.txt -n表示显示过滤出的内容是在那一行
、
3.5、[ ]的使用
[]:匹配中括号中指定的任意字符,且只匹配一个字符,比如[aos]:表示只匹配aos这三个其中的一个
grep -n "s[ao]id" test.txt
还有[0-9]:会匹配任意一个数字,例如:
grep -n "[0-9]" test.txt
还有[A-Z]:表示配置任意一个大写的字母,如果是" ^[a-z]":表示代表匹配以小写字符以外的任意一个字符,这里需要注意的就是^在[]外面表示行首,
如果在[]里面笔试取反,如^[a-z]:表示一任意一个小写的字母为开头,而,"^[^a-z]":表示不一任意一个小写的字母为开头
^[^a-zA-Z]:这个表示不一字母为开头,你们可以试试看看效果
3.6、"\"的作用
"\":表示转义符,就表示将这些带有效果的符号就表示原本的值,例如匹配一 .为结尾的,那就是 .$,但是 . 在正则中以表示特殊的含义
这事就要在.的前面加上"\"符号将他的特殊的含义去掉,同样也可以将一个原本没有使用含义功能的符合赋予含义如{},下面会说这个{}的作用
可以看到如果不带\就回将任意字符为结尾的行都匹配出来了
3.7、"\{n\}"的使用
"\{n\}": 表示前面的字符可以出现n次,比如 zo\{3\}m就表示匹配zooom这个字符串,而如果是\{n,\}则表示一个范围数了,这表示n次到无数次
比如 \{3,\}:表示前面的字符可以出现3次到无数次,但至少是三次,即{}就表示前面字符出现次数的一个范围
grep -n "[0-9]\{3\}" test.txt 与上面的[]结合使用,表示0-9数字之间任意连续在一起出现三次
范围匹配:
grep -n "sa\{1,3\}i" test.txt 表示前面的a出现1到3次
四、扩展元字符的使用案例
4.1、"|"
"|"或 扩展元字符有所不同,grep过滤的时候需要加上-E或者egrep进行过滤
比如过滤出sshd配置文件中有效信息,去除注释一空行
egrep -nv "^#|^$" /etc/ssh/sshd_config -v表示取反的意思,^#:表示匹配一#为开头的注释行,^$匹配空行 加上-v取反一下即可
4.2、过滤IP地址
先分享将这个ip划分为四段来,在讲ip地址从0-255之间进行拆分,0-99,100-199,200-249,250-255
egrep "\<(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})){3}\>" /etc/hosts
这里的\< :表示开始 \>:表示结束
也可以过滤手机号的,例如: egrep "\<1[3|4|5|6|7|8][0-9]{9} \>" 文件名 感兴趣的可以试试
4.3、"+","?这两个符号的效果
可以查看+表示匹配前面的字符出现一次或多次,?表示0次或1次
类似符合总结:
*: 表示前面的字符出现任意多次, 与+类似 +:表示前面的字符出现1到多次不包含0次而已
. :表示任意一个字符可以任意一个字符 而?表示前面的字符出现0次或者1次
组合 .*表示任何长度的任意字符可以理解表示所有
^ : 以什么什么开头 $:以什么什么结尾 ^$即表示匹配为空行
():表示将()里面的看成一个整体如果里面有空格也会看做的要注意
\{\}:表示前面的字符出现的次数的一个范围,要比+、*、?等要灵活一些
\< \>:表示开始与介绍符
[ ] :表示匹配取值的范围如 [0-9a-zA-Z]:表示匹配人一个0-9的数字或a-z的大小写字母