正则表达式使用总结

12 篇文章 1 订阅
4 篇文章 0 订阅

最简单的例子

正则表达式广泛应用于文本处理中。Linux中常用的命令工具grep,sed,awk等都支持正则表达式;流行的编程语言JavaScript和Python也都内置对正则表达式的支持。因此掌握正则表达式的知识,对很多领域都有帮助。

以grep命令为例,先来看看最简单的例子。比如,想要查看Linux下/etc/passwd中的root账户信息:

grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
dockerroot:x:496:492:Docker User:/var/lib/docker:/sbin/nologin

 

上面的例子使用"root"来进行匹配,结果不仅列出了root账户的信息,还列出了其它账户的信息。为了限定为root账户,需要匹配以root开头的行。为此采用下面的命令

grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

其中的"^root"就是一个简单的正则表达式,其中的"^"表示在行首匹配字符串。

正则表达式的基本结构

新的正则表达式定义于IEEE的标准1003.2文档中,也称为POSIX 1003.2文档。一个正则表达式的基本形式为:

分支|分支|...

即一个正则表达式由一个或者多个非空的分支(branch)组成,中间由"|"隔开。输入字符串只要匹配其中的一个分支就表示匹配了这个正则表达式,即其中的"|"表示或的关系。

而每个分支又由一个或多个相连的片段(piece)组成。在匹配一个分支时,它先匹配第一个片段,匹配上则匹配第二个片段,以此类推。因此片段之间是与的关系。

分支:=片段片段片段...

而每个片段则有两部分组成:

  • 原子表达式(atom)
  • 限定符表达式(*,+,?,{})

即:

片段:=atom限定

原子表达式(atom)

原子表达式(atom)有以下几种形式:

形式说明
普通字符直接匹配,如第一个例子中的"root"
()匹配空字符串
.匹配任意单一字符
^匹配行首的空字符串。比如^root的严格意义是^匹配行首空字符串,接着匹配root,这意味着行首为root。
$匹配行尾的空字符串
[][]表达式
(正则表达式)匹配一个正则表达式。将一个正则表达式用()扩起来后,它又可以作为一个元表达式,从而与限定符组成piece,再进一步组成branch和更复杂的正则表达式。因此()表达式允许嵌套使用正则表达式。
原义字符'\'加上特殊字符'^.[$()|*+?{\'中的一个,用来匹配特殊字符本身。比如,特殊字符'^'表示匹配行首空字符串;但是'\^'则表示匹配'^'本身。
转义字符以'\'开头的转移字符,如'\n'表示换行符号;'\r'表示回车符;'\s'表示空白字符[\n\r\t\v\f],'\S'则表示任何非空白字符[^\n\r\t\v\f],等等。

[]表达式

方括号表达式就是用[]扩起来的一串字符。典型的情况下,它表示匹配这串字符中的任意一个。例如'[abcde]'匹配字符'a,b,c,d,e'中的任意一个。举个例子,如果想要查找/etc/passwd中的'ftp'和'ntp'账号的信息,就可以采用如下正则表达式:

egrep "^[fn]tp" /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin

这里的egrep命令即"grep -E",选项-E表示支持POSIX标准正则表达式。

 

[]表达式中还可以使用'-'来表示范围。例如,'[a-z]'表示字母'a'到'z'之间的任意一个字母(包含'a'和'z')。类似地,[0-9]则表示'0'-'9'。比如,要查找/etc/passwd中用户ID小于10的账号信息,可以用如下命令:

egrep "^[^0-9]+:[0-9]:" /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

这么写的目的是为了避免匹配用户ID大于10但组ID小于10的账号。

 

对于排序符号(colloating-symbol),采用"[."和".]"来表示。排序符号的定义是和本地化设置(locale)有关联的。每一个locale设置,都对应有对应的排序符号定义。"[."和".]"中只能引用定义的排序符号,而不能自己随便乱写,否则会报错。

举个例子,为了查看en_US的排序符号,首先使用编辑器打开/usr/share/i18n/locales/en_US,然后找到LC_COLLATE部分。

vi /usr/share/i18n/locales/en_US
LC_COLLATE

% Copy the template from ISO/IEC 14651
copy "iso14651_t1"

END LC_COLLATE

可以看到,en_US的排序符号定义采用的是iso14651_t1,进一步打开这个文件。

 vi /usr/share/i18n/locales/iso14651_t1
LC_COLLATE

copy "iso14651_t1_common"

script <HAN>

order_start <HAN>;forward;forward;forward;forward,position
<U4E00> <U4E00>;IGNORE;IGNORE;IGNORE
.. ..;IGNORE;IGNORE;IGNORE
<U9FA5> <U9FA5>;IGNORE;IGNORE;IGNORE
#
order_end
#
END LC_COLLATE

再查看iso14651_t1_common,并查找collating-symbol:

vi /usr/share/i18n/locales/iso14651_t1_common
#
collating-symbol <0>
collating-symbol <1>
collating-symbol <2>
collating-symbol <3>
collating-symbol <4>
collating-symbol <5>
collating-symbol <6>
collating-symbol <7>
collating-symbol <8>
collating-symbol <9>
#
collating-symbol <a>
collating-symbol <b>
collating-symbol <c>
collating-symbol <d>
collating-symbol <e>
collating-symbol <f>
collating-symbol <g>
collating-symbol <h>

 

[]表达式还支持一种便捷的类别表示法,即"[:"和":]"之间放入类别,比如"[:alnum:]"表示字母和数字, "[:upper:]"表示大写字母。支持的类别有以下一些:

           alnum    digit    punct
           alpha    graph    space
           blank    lower    upper
           cntrl    print    xdigit

前面匹配用户ID小于10的例子,也可以写成如下:

egrep "[[:alpha:]]+:[[:digit:]]:" /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

范围及范围表达式{}

范围限定符包括'+','*'和'?',分别表示1次及以上(至少1次),0次及以上,0次或1次(至多1次)。范围表达式则用{}扩起来,可以有一个到两个整数指定范围。比如'+'也可以表示成{1,};'*'可以表示成{0,};'?'则可以表示成{,1}。而{m,n}则表示最少出现m次,最多出现n次。

一个综合例子

比如想要匹配"2020-12-28"或者"2020/12/28"这样的日期格式:

echo "2020/12/28" | egrep "^[[:digit:]]{4}(\-|\/)[[:digit:]]{1,2}\1[[:digit:]]{1,2}$"
2020/12/28
echo "2020-12-28" | egrep "^[[:digit:]]{4}(\-|\/)[[:digit:]]{1,2}\1[[:digit:]]{1,2}$"
2020-12-28

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值