一、简介

        正则表达式分为 基本正则表达式 和 扩展正则表达式 ,两者其实基本用法都一样,但是在某些符号的写法上有差异,接下来,我将一步一步带领大家学习正则表达式

演示文本:
# vim test1.txt

root ROOT Rootabroot
tom jerrytom Tom
123 56789

SElinux=disabled
#selinux firewalld
abc ABC .rootROOT
abcrootabcc
abcabc
babcabcabcbaaa abcbbb
aaaaa bbbbbb
tm ttm ttttttm

# head -10 /etc/passwd > passwd

二、基本正则表达式:入门

^:表示锚定行首,此字符后面的任意内容必须出现在行首,才能匹配。
匹配以root开头的行
# grep "^root" test1.txt

$:表示锚定行尾,此字符前面的任意内容必须出现在行尾,才能匹配。
匹配以root结尾的行
# grep "root$" test1.txt

^$:表示匹配空行,这里所描述的空行表示”回车”,而”空格”或”tab”等都不能算作此处所描述的空行。
每一行的结尾默认都会有$结尾符,在vim中可以使用set list显示$
匹配以$开头的行,也就是空行
# grep "^$" test1.txt
grep -n -v -e "^$" -e "^#" test1.txt

^abc$:表示abc独占一行时,会被匹配到。
# grep -n "^abc$" test1.txt

\<或者\b :匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现。
# grep "\<root" test1.txt
# grep "\broot" test1.txt

\>或者\b :匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现。
# grep "root\>" test1.txt
# grep "root\b" test1.txt


\B:匹配非单词边界,与\b正好相反。
# grep "\Broot" test1.txt 
# grep "root\B" test1.txt 
# grep "\Broot\B" test1.txt

总结(用自己的话阐述这些符号的作用)
^
$
^$
^abc$
\<或者\b
\>或者\b
\B

三、基本正则表达式:连续匹配次数

* 表示前面的字符连续出现任意次,包括0次。
# grep "t*m" test1.txt
# grep "b*" test1.txt
# grep "\(abc\)*" test1.txt

.  表示任意单个字符。
# grep "a....b" test1.txt

.* 表示任意长度的任意字符,与通配符中的*的意思相同。
# grep "a.*b" test1.txt
# grep "r.*t" test1.txt

\? 表示匹配其前面的字符0或1次
# grep "abc\?" test1.txt

\+ 表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
# grep "abc\+" test1.txt

\{n\} 表示前面的字符连续出现n次,将会被匹配到。
# grep "a\{3\}" test1.txt
# grep "\(abc\)\{2\}" test1.txt
# grep "\<\(abc\)\{2\}\>" test1.txt

\{x,y\} 表示之前的字符至少连续出现x次,最多连续出现y次,都能被匹配到,换句话说,只要之前的字符连续出现的次数在x与y之间,即可被匹配到。
# grep "a\{2,4\}" test1.txt 
# grep "\(abc\)\{1,3\}" test1.txt
# grep "\<\(abc\)\{1,3\}\>" test1.txt

\{,n\} 表示之前的字符连续出现至多n次,最少0次,都会被匹配到。
# grep "a\{,4\}" test1.txt 

\{n,\} 表示之前的字符连续出现至少n次,才会被匹配到。
# grep "a\{3,\}" test1.txt

注意:
如果匹配的是一个单词整体,需要小括号括起来,例如: \(abc\)

总结(用自己的话阐述这些符号的作用)
*
.
.*
\?
\+
\{n\}
\{n,\}
\{,m\}
\{n,m\}

四、基本正则表达式:常用匹配

字符
.  表示匹配任意单个字符
* 表示匹配前面的字符任意次,包括0次
[  ] 表示匹配指定范围内的任意单个字符
[^  ] 表示匹配指定范围外的任意单个字符

[0-9]               匹配0-9的数字
[a-z]               匹配a-z的小写字母
[A-Z]              匹配A-Z的大写字母
[a-zA-Z]         匹配所有的大小写字母
[a-zA-Z0-9]    匹配所有的大小写字母和数字

分组
\( \) 表示分组,我们可以将其中的内容当做一个整体,分组可以嵌套。
\(abc\) 表示将abc当做一个整体去处理。

转义符\
例如.是匹配任意单个字符,那么\.表示的就是.原本的意思
要注意,如果转移\\,那么需要用单引号,不能用双引号

举例:匹配ip地址
# ifconfig | grep "\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}"
# grep "\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}$" /etc/sysconfig/network-scripts/ifcfg-ens33

总结(用自己的话阐述这些符号的作用)

[  ]
[^  ]
[0-9]           
[a-z]              
[A-Z]              
[a-zA-Z]        
[a-zA-Z0-9]    
\( \)
\(abc\)

基本正则大总结:

^         
$    
^$     
^abc$
\<或者\b
\>或者\b
\B
*
.
.*
\?
\+
\{n\}
\{n,\}
\{,m\}
\{n,m\}
[  ]
[^  ]
[0-9]           
[a-z]              
[A-Z]              
[a-zA-Z]        
[a-zA-Z0-9]    
\( \)
\(abc\)

五、扩展正则表达式

扩展正则与基本正则的区别

扩展正则

( ) 表示分组
(ab) 表示将ab当做一个整体去处理。

?  表示匹配其前面的字符0或1次
+  表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
{n} 表示前面的字符连续出现n次,将会被匹配到。
{x,y} 表示之前的字符至少连续出现x次,最多连续出现y次,都能被匹配到,换句话说,只要之前的字符连续出现的次数在x与y之间,即可被匹配到。
{,n} 表示之前的字符连续出现至多n次,最少0次,都会陪匹配到。
{n,}表示之前的字符连续出现至少n次,才会被匹配到。
"|"在扩展正则表达式中,表示”或”

基本正则

\( \)
\(abc\)
\?
\+
\{n\}
\{n,\}
\{,m\}
\{n,m\}
\|

扩展正则与基本正则表达式的用法基本相同,但是扩展正则的写法更加简练,例如
扩展正则写法
# egrep "(abc){1,3}" test1.txt 
# egrep "^(root|bin)" passwd
基本正则写法
# grep "\(abc\)\{1,3\}" test1.txt 
# grep "^\(root\|bin\)" passwd

将括号里面看作是一个整体,表示为root或bin,所以"^(root|bin)"表示以root开头的行或者以bin开头的行

扩展正则总结

常用符号
.   表示任意单个字符。
*  表示前面的字符连续出现任意次,包括0次。
.* 表示任意长度的任意字符,与通配符中的*的意思相同。
\  表示转义符,当与正则表达式中的符号结合时表示符号本身。
| 表示"或者"之意
[  ]表示匹配指定范围内的任意单个字符。
[^  ]表示匹配指定范围外的任意单个字符。
 
次数匹配相关
?  表示匹配其前面的字符0或1次
+  表示匹配其前面的字符至少1次,或者连续多次,连续次数上不封顶。
{n} 表示前面的字符连续出现n次,将会被匹配到。
{x,y} 表示之前的字符至少连续出现x次,最多连续出现y次,都能被匹配到,换句话说,只要之前的字符连续出现的次数在x与y之间,即可被匹配到。
{,n} 表示之前的字符连续出现至多n次,最少0次,都会陪匹配到。
{n,}表示之前的字符连续出现至少n次,才会被匹配到。

位置边界匹配相关
^:表示锚定行首,此字符后面的任意内容必须出现在行首,才能匹配。
$:表示锚定行尾,此字符前面的任意内容必须出现在行尾,才能匹配。
^$:表示匹配空行,这里所描述的空行表示"回车",而"空格"或"tab"等都不能算作此处所描述的空行。
^abc$:表示abc独占一行时,会被匹配到。
\<或者\b :匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现。
\>或者\b :匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现。
\B:匹配非单词边界,与\b正好相反。
 
分组与后向引用
( ) 表示分组,我们可以将其中的内容当做一个整体,分组可以嵌套。
(ab) 表示将ab当做一个整体去处理。
"|"在扩展正则表达式中,表示"或",多数在分组里面使用

六、实战演练

举例1:按照规定找出合法邮箱,满足如下条件

1、邮箱字符串中必须包含"@"符
2、"@"符前面的字符只能是小写字母或数字,不能包含特殊符号。
3、"@"符前面的字符数量至少需要4个,至多为16个
4、邮箱必须以"com"、"net"、"org"、"edu"等顶级域名结尾(此处为了方便演示,不判断更多的域名)
5、顶级域名之前必须包含一个”点”,换句话说就是,邮箱必须以"com"、"net"、"org"、"edu"结尾
6、"@"与"."之间的字符数量不能超过12个,不能低于2个
7、"@"与"."之间的字符只能是小写字母或数字,不能包含特殊符号


基本正则
# grep "[a-z0-9]\{4,16\}@[a-z0-9]\{2,12\}\.\<\(com\|net\|org\|edu\)$" qq.txt

扩展正则
# egrep "[a-z0-9]{4,16}@[a-z0-9]{2,12}\.\<(com|net|org|edu)$" qq.txt 

思考:
# 为什么要添加\<词首符号?
为了确保必须以.com结尾,不会出现.aaacom的情况

举例二:匹配IP地址

# cat ip.txt 
192.168.58.100
256.256.55.55
255.255.0.256
59.59.58.58
0.5.5.5
198.198.198.300
8.8.114.114

没有经过校验

基本正则
grep "\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}" ip.txt

扩展正则
egrep "([0-9]{1,3}\.){3}[0-9]{1,3}" ip.txt

经过校验

第一个
1-9               [1-9]
10-99           [1-9][0-9]
100-199       1[0-9]{2}
200-249       2[0-4][0-9]
250-255       25[0-5]

第二、三、四
0-9               [0-9]
10-99           [1-9][0-9]
100-199       1[0-9]{2}
200-249       2[0-4][0-9]
250-255       25[0-5]

注意: 
1、此处校验IP[0-9]不能使用\d表示
2、使用|表示或,使用()表示一个整体

基本正则
grep "\([1-9]\|[1-9][0-9]\|1[0-9]\{2\}\|2[0-4][0-9]\|25[0-5]\)\.\([0-9]\|[1-9][0-9]\|1[0-9]\{2\}\|2[0-4][0-9]\|25[0-5]\)\.\([1-9]\|[1-9][0-9]\|1[0-9]\{2\}\|2[0-4][0-9]\|25[0-5]\)\.\([1-9]\|[1-9][0-9]\|1[0-9]\{2\}\|2[0-4][0-9]\|25[0-5]\)$" ip.txt

扩展正则
egrep "([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$" ip.txt

七、正则表达式的其他字符、

[[:alpha:]]  表示任意大小写字母
[[:lower:]]  表示任意小写字母
[[:upper:]]  表示任意大写字母
[[:digit:]]  表示0到9之间的任意单个数字(包括0和9)
[[:alnum:]]  表示任意数字或字母
[[:space:]]  表示任意空白字符,包括"空格"、"tab键"等。
[[:punct:]]  表示任意标点符号
 
[0-9]与[[:digit:]]等效
[a-z]与[[:lower:]]等效
[A-Z]与[[:upper:]]等效
[a-zA-Z]与[[:alpha:]]等效
[a-zA-Z0-9]与[[:alnum:]]等效
 
[^0-9]与[^[:digit:]]等效
[^a-z]与[^[:lower:]]等效
[^A-Z]与[^[:upper:]]等效
[^a-zA-Z]与[^[:alpha:]]等效
[^a-zA-Z0-9]与[^[:alnum:]]等效
 
#简短格式并非所有正则表达式解析器都可以识别
\d 表示任意单个0到9的数字
\D 表示任意单个非数字字符
\t 表示匹配单个横向制表符(相当于一个tab键)
\s表示匹配单个空白字符,包括"空格","tab制表符"等
\S表示匹配单个非空白字符

\1 表示引用整个表达式中第1个分组中的正则匹配到的结果。
\2 表示引用整个表达式中第2个分组中的正则匹配到的结果。