基本正则表达式与扩展正则表达式的使用以及可能应用到的场景

正则表达式

1. 什么是正则表达式

简单地说,正则表达式是一种符号表示法,用于识别文本模式。在某种程度上,它们类似于匹配文件和路径名时使用的shell通配符,但其用途更广泛。许多命令行工具和大多数编程语言都支持正则表达式,以此来解决文本操作方面的问题。然而,在不同的工具,以及不同的编程语言之间,正则表达式都会略有不同,这让事情进一步麻烦起来。方便起见,我们将正则表达式的讨论限定在POSIX标准中(它涵盖了大多数命令行工具),与许多编程语言(最著名的Perl)不同,这些编程语言使用的符号集要更多一些。

2. 正则表达式分类

正则表达式:REGEXP,REGular EXPression。
正则表达式分为两类:

  • Basic REGEXP(基本正则表达式)
  • Extended REGEXP(扩展正则表达式)

3. 基本正则表达式

[root@redhat ~]# ls
1   2  4  6  8  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
10  3  5  7  9  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
//元字符
    .           //任意单个字符
    []          //匹配指定范围内的任意单个字符
    [^]         //匹配指定范围外的任意单个字符(取反)
    
效果测试:
[root@redhat ~]# ls | grep '[adf]'   //不能用,或空格分隔字符,不然会把,和空格当做单个字符进行匹配
a
d
f
[root@redhat ~]# ls | grep '[^adf]'   //加上^则取出除adf这三个单个字符以外任意的单个字符
[root@redhat ~]# ls | grep '[a-z]'    //将a到z全部匹配出来,若换成[a-Z]则是从小写a匹配到大写Z
a
b
c
d
e
f
g
省略. . .
t
u
v
w
x
y
z
[root@redhat ~]# ls | grep '[^a-Z]'   //取除了从小写a到大写Z以外的任意单个字符
1
10
2
3
4
5
6
7
8
9

补充:转义“ \ ”

在正则表达式中有些许字符我们不想让他呈现他原本的含义,例如“|”是管道符,将前面命令所执行出来的结果作为后面命令的参数,“^”是指定开头的字符,“$”是指定结尾的字符,而当我们在某些情况下使用到这些字符的时候,他所呈现的结果不是我们想用到的,这种时候就需要我们将他的含义转变,也就是转义(改变他表达的含义),需要我么用到“ \ ”。
效果测试:
[root@redhat ~]# ls
'^'   2   5   8   A     B   d   E   g   H   j   K   m   N   p   Q   s   T   v   W   y   Z
 1    3   6   9   abc   c   D   f   G   i   J   l   M   o   P   r   S   u   V   x   Y
 10   4   7   a   b     C   e   F   h   I   k   L   n   O   q   R   t   U   w   X   z
 
 此时我们想要匹配到“^”这个字符,正常情况下我们会进行如下操作:
 [root@redhat ~]# ls | grep '[^]'
 grep: Unmatched [, [^, [:, [., or [=    //显示我们语法有问题,这里他就是把“^”当做指定开头的字符了
 
 我们的正确做法则是应该改变他的原本含义,如下:
 [root@redhat ~]# ls | grep '[\^]'     //将“^”转义,让他就表示“^”这个字符
 ^
 
 同时我们也可以在多个匹配中将“^”放在后面,如下:
 [root@redhat ~]# ls | grep '[235^]'
^
2
3
5
[root@redhat ~]# ls
'^'   11   3    5   8   A     B   d   E   g   H   j   K   m   N   p   Q   s   T   v   W   y   Z
 1    2    33   6   9   abc   c   D   f   G   i   J   l   M   o   P   r   S   u   V   x   Y
 10   22   4    7   a   b     C   e   F   h   I   k   L   n   O   q   R   t   U   w   X   z
//匹配次数(贪婪模式)
    *           //匹配其前面的任意单个字符任意次
    .*          //任意长度的任意字符,正则表达式中的.*就是通配符里面的*
    \?          //匹配其前面的任意单个字符1次或0次
    \+          //匹配其前面的任意单个字符至少1次
    \{m,n\}     //匹配其前面的任意单个字符至少m次,至多n次

效果测试:
[root@redhat ~]# ls | grep '^[123]*$'
1
11
2
22
3
33

[root@redhat ~]# ls | grep '^1\?$'    //匹配前面一个字符0次或1次,0次就代表没有,所以只有1次
1
[root@redhat ~]# ls | grep '^11\?$'
1
11

[root@redhat ~]# touch ba baa baaa
[root@redhat ~]# ls | grep '^ba\+$'   //匹配前面一个字符,最少一次
ba
baa
baaa

[root@redhat ~]# ls | grep '^ba\{2,3\}$'   //匹配前面的单个字符最少2次,最多3次
baa
baaa

//位置锚定
    ^           //锚定行首,此字符后面的任意单个字符必须出现在行首
    $           //锚定行尾,此字符前面的任意单个字符必须出现在行尾
    ^$          //空白行
    \<或\b       //锚定词首,其后面的任意单个字符必须作为单词首部出现
    \>或\b       //锚定词尾,其前面的任意单个字符必须作为单词尾部出现
/分组
    \(\)
    例:\(ab\)*
    //后向引用
        \1      //引用第一个左括号以及与之对应的右括号所包括的所有内容
        \2      //引用第二个左括号以及与之对应的右括号所包括的所有内容
        
效果如下:
[root@redhat ~]# vim abc 
[root@redhat ~]# cat abc
hello 0714-2564851 hehe
(+86)13872364194
1514864158
                             //此处有一行空白行
[root@redhat ~]# cat abc | grep '^$'     //匹配空白行

[root@redhat ~]# cat abc | grep -v '^$'  //通过-v选项取反,取出不是空白行的行
hello 0714-2564851 hehe
(+86)13872364194
1514864158

[root@redhat ~]# echo "hello world hello1 tom hello zhangsan" | grep ' \<hello\>'
hello world hello1 tom hello zhangsan   //hello1中确实是hello开头,但不是hello结尾,所以只会匹配到第三个hello

[root@redhat ~]# touch ab abab ababab abababab
[root@redhat ~]# ls |grep '^\(ab\)\?$'
ab
[root@redhat ~]# ls |grep '^\(ab\)\1$'      //引用第一个左括号以及与之对应的右括号所包括的所有内容
abab
[root@redhat ~]# touch abdcdc
[root@redhat ~]# ls |grep '^\(ab\)\(dc\)\2$' //引用第二个左括号以及与之对应的右括号所包括的所有内容
abdcdc

扩展内容:
将 hello world ftx 中的world 和 ftx互换一下位置
[root@redhat ~]# echo 'hello world ftx' | sed 's/hello \(.*\) \(.*\)/hello \2 \1/g'
hello ftx world    //.*是前面说过的匹配任意长度的字符,\2引用前面第2个括号的内容,\1引用前面第1个括号的内容

4. 扩展正则表达式

//字符匹配
    .       //匹配任意单个字符
    []      //匹配指定范围内的任意单个字符
    [^]     //匹配指定范围外的任意单个字符
//次数匹配
    *       //匹配其前面的任意单个字符任意次
    ?       //匹配其前面的任意单个字符1次或0次
    +       //匹配其前面的任意单个字符至少1次
    {m,n}   //匹配其前面的任意单个字符至少m次,至多n次

//位置锚定
    ^       //锚定行首,此字符后面的任意单个字符必须出现在行首
    $       //锚定行尾,此字符前面的任意单个字符必须出现在行尾
    ^$      //空白行
    \<或\b       //锚定词首,其后面的任意单个字符必须作为单词首部出现
    \>或\b       //锚定词尾,其前面的任意单个字符必须作为单词尾部出现
//分组
    ()      //分组
    \1,\2,\3,....
   例:(ab)*
    //后向引用
        \1      //引用第一个左括号以及与之对应的右括号所包括的所有内容
        \2      //引用第二个左括号以及与之对应的右括号所包括的所有内容
//或者
    |       //or 默认匹配|的整个左侧或者整个右侧的内容
    //例:C|cat表示C或者cat,要想表示Cat或者cat则需要使用分组,如(C|c)at

5.扩展正则表达式的优点

扩展正则表达式相对于基本正则优化了一些命令语法问题,使正则表达式更加简洁、易懂。
//加上-E选项,使用扩展正则表达式
效果如下:
[root@redhat ~]# echo 'hello world ftx' | sed -E 's/hello (.*) (.*)/hello \2 \1/g'
hello ftx world
[root@redhat ~]# ls |grep -E '^(ab)(dc)\2$'
abdcdc

由上述两个执行出来的效果可以看出,扩展正则表达式基本上和基本正则表达式相同,这是因为扩展正则表达式是基于基本正则表达式优化之后的,最容易看出的点就是我们不再需要使用转义“^”来改变他的含义

[root@redhat ~]# touch c cat
[root@redhat ~]# ls | grep '^c\|cat$'
c
cat
[root@redhat ~]# ls | grep -E '^c|cat$'
c
cat
[root@redhat ~]# touch Cat cat
[root@redhat ~]# ls | grep '^Cat\|cat'
cat
Cat
[root@redhat ~]# ls | grep -E '^Cat|cat'
cat
Cat
[root@redhat ~]# ls | grep -E '^(C|c)at'
cat
Cat

使用场景

在我们工作中,分有可能会出现让你在一些文本内容中提取一些有用的信息,这种时候我们就需要用到正则表达式去将他匹配提取出来。

提取abc文件中的座机号码
[root@redhat ~]# cat abc
hello 0714-2564851 hehe
(+86)13872364194
15148641584

(0235)5766813
12345678910
[root@redhat ~]# cat abc | grep -E '\(?0[0-9]{3}\)?-?[0-9]{7}'
hello 0714-2564851 hehe
(0235)5766813

思路分析:
'\(?0[0-9]{3}\)?-?[0-9]{7}'

\(? 是将(转义成为单纯的一个符号,加上?是因为他可能没有(也可能有(,所以我们将他匹配0次或1次
0[0-9]{3} 中第一个0是因为座机号一般开头都为0,所以我们可以直接确认,[0-9]是匹配单个字符从0-9,{3}则是前面的匹配的次数,此处为3次,因为座机中可能会出现-,而-前一般都是4个数字,在我们确定了第一个数字为0后,我们就只需要匹配后面三个数字
-? 就是匹配 “-” 0次或1次,因为-可能有可能没有
[0-9]{7}则是匹配后面的7位数字
//由此就可以匹配出我们想要的结果



//理解各个正则表达式的用法之后我们就可以很轻易的完成查询工作,手机号码的提取亦是如此:
同样是abc这个文件中的内容
[root@redhat ~]# cat abc
hello 0714-2564851 hehe
(+86)13872364194
15148641584

(0235)5766813
12345678910

//同样的思路,但是在日常生活中我们需要有一定的常识,我们都知道各大运营商的手机号开头都是有规定的,比方说138,155,177,183,191,国内手机号首位一定1,而在第二位就有了要求,现在手机号的第二位只有3,5,7,8,9,所以我们在匹配时需要考虑到这一点,某些情况下还需要将手机号前的国际区号(+86)这类信息提取出来,整理完思绪后得出的结果如下:
[root@redhat ~]# cat abc | grep -E '(\(\+86\))?1[35789][0-9]{9}'
(+86)13872364194
15148641584

如果没有上述的基本常识,则会出现一下情况:
[root@redhat ~]# cat abc | grep -E '(\(\+86\))?1[0-9]{10}'
(+86)13872364194
15148641584
12345678910    //很显然,这行不为手机号的行也匹配出来了
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值