正则表达式中常⽤符号
⼀:
正则在Perl、Py森、Ruby、Java等语⾔中⽂本的正则表达式⼏乎是⼀样的
以前常⽤到的在⽹上都有现成的例⼦拿来⽤,⽐如电话格式、邮箱格式之类的。
但是⾃然语⾔处理中往往会根据⾃⼰的需求来制定⼀个表达式,如果正则的知识掌握的⽐较⽚⾯,在编写⾃然语⾔处理程序时可能会觉得苦恼。
在《⾃然语⾔处理简明教程》⾥⾯有很系统的正则表达式教程,特意总结出来消化吸收。
⼆:
双斜线“//”
最简单的正则表达式就是这样的,由类似于/hello world /的正则来搜索语料库中包含⼦字符串“hello world”的任何字符串相匹配。/e/是可以匹配到字符串hello的。
中括号“[]”
[]会匹配其中的某⼀个字符。⽐如现在有嫌疑⼈,我们只知道他的名字可能是下⾯三种的某⼀种,分别是张伟、李伟或者黄伟。就可以使⽤/[张李黄]伟/来在⼈⼝数据库中匹配。
{}表⽰限制长度。如:.{1}表⽰匹配⼀个任意字符
连字符“-”
⽤来划定范围,表⽰某⼀范围内的任何字符。⽐如上个例⼦⾥⾯的/[1234567890]/是不是感觉很不⽅便。如果表⽰为/[0-9]/就会显得精简的多。
正则匹配
/李太?⽩/ /times?/“李⽩”或者“李太⽩”time或者times
脱字符“^”
如果在⽅括号之后有脱字符“^”,对应的模式就是否定的。
问号“?”
⽐如我们在语料库中搜索诗⼈“李⽩”或者“李太⽩”,此时⽅括号就⽆法帮助我们,因为[]只能表⽰xx或者XX,但是不能表⽰有xx或者没xx。此时可以⽤“?”来表⽰前⼀个字符有或者⽆。
“Kleene*”
当正则表达式⽤来表⽰重复的字符时,⽐如在下载⽂件时,出现了下⾯的下载进度:
99.9%
99.99%
99.999%
99.9999%
……
正则匹配模式例⼦
/[beg.n]/beg和n中包含⼀个字符的字
符串begin,beg‘n,begun
此时我们可以⽤/9*/来表⽰重复了“0或者若⼲次”的字符“9”,因此想表⽰出现了⼀次或者多次的“9”,需要⽤/99*/。
因此/99\.99*%/可以⽤来表⽰上述进度条。(此处的“.”需要转译,因为我们不想让他表⽰为通配符)
稍微复杂点:
/[10]*/可以⽤来表⽰⼀个⼆进制串,⽐如“1010100001110001”
“Kleene+”
但是我⽤/99*/来表⽰重复了“0或者若⼲次”的字符“9”时总觉得多写了⼀个“9”很不爽,这时有没有办法帮我们省掉多打⼀个“9”的时间呢?
/9+/就可以了~
因此使⽤/[10]+/来搜索语料中的⼆进制字符串看起来更顺⼿
通配符“.”
哎那个马什么民,帮我把袜⼦洗⼀下。
这样说话是很不礼貌的,但是当我们确实忘了别⼈名字时怎么办呢?
正则表达式同样可以解决这个问题。
正则⾥⾯有⼀个点号,通配符(/./)可以表⽰任何字符。
/马.民/可以在你的班级花名册⾥⾯搜索到所有叫“马X民”的⼈。
当/./和/*/或者/+/碰到时,什么神奇的事情会发⽣呢?
⽐如我们想知道有⼀天马X民对黄伟做了什么事情,怎么写正则来在班级⽇志⾥⾯缩⼩搜索范围呢?
/马.民.+黄伟/就可以表⽰在⼀个长字符串⾥⾯,符合马X民bulabula黄伟的句⼦。
锚号“^”和“$”
顾名思义,锚号是⽤来把正则“锚”在字符串的特定位置的。最普通的锚号是“^”和“$”,当“^”⽤作锚号的时候,表⽰⼀⾏的开始。⽐
如/^The/就表⽰单词The必须出现在⼀句话的开头。相反“$”表⽰⼀⾏的结尾。
回到上⾯的例⼦,⽐如我们想在班级⽇志⾥⾯到“马兴民xxx黄伟。”这样的句⼦,就可以使⽤锚号来定位。/^马兴民.+黄伟。$/
词界“\b”“\B”
\b表⽰词界,\B表⽰⾮词界。
⾸先,在计算机语⾔⾥⾯,什么是⼀个词呢。从技术上说,词被定义为数字、下划线、或者字母的任
何序列。
⽐如我们在搜索单词“a”的时候,如果仅仅⽤/a/,同样会匹配到类似于“happy”这样的单词,但是如果⽤/\ba\b/的话,就会只到单词a。
⽐如“I am a handsome man.”
正则扩充表达式匹配
\d \D \w \W \s \S
[0-9]
[^0-9]perl是用来干嘛的
[a-zA-Z0-9]
[^\w]
[_\r\t\n\f]
[^\s]
数字字符
⾮数字字符
数字字母下划线
相反
表格,换⾏等空⽩区域
⾮空⽩区域
正则匹配
* + ? {n} {n,m} {n,}
零或多⼀或多零或⼀出现n次n到m次⾄少n次
它仅仅会匹配到单词“a”⽽⾮“am”。
析取符“|”
析取符表⽰或者。
前⾯有个⼩伙⼦很眼熟,我记得他的名字叫马兴民或者黄伟。现在我打开在线班级花名册,输⼊正则/黄伟|马兴民/,⼀下就到了两个⼈的信息和照⽚,⼀看哦都不是。
析取符就是⽤来表⽰或者,/a|b/表⽰a或者b。
在英⽂语料中,有时候会出现名词的复数形式⽐如cat和cats,这种形式我们很容易表达。但是有些复数⽐如family的复数families该如何表达呢。
⾸先famil串已经是固定的了,这时我们只需要尾串跟上y或者ies即可,此时我们使⽤圆括号运算符(),将⼀个模式括起来,使得它就像⼀个单独的字符。因此如果我们想到语料中的family和families时,需要⽤/famil(y|ies)/,析取符仅仅运⽤于后缀y或者ies。
三:
通⽤字符集的替换
计数符
? 贪婪模式与⾮贪婪模式
⽐如在HTML中有许多标签<div>part1</div><div>part2</div><div>part3</div><div>part4</div>
使⽤<div>.*</div>匹配到的是:<div>part1</div><div>part2</div><div>part3</div><div>part4</div>,此时为贪婪模式。
使⽤<div>.*?</div>匹配到的是:<div>part1</div>
(?<=exp) (?=exp)零宽断⾔
(?<=exp) 表⽰匹配exp之后的,(?=exp)表⽰匹配exp之前的。
⽐如上⾯标签例⼦:<div>part1</div><div>part2</div><div>part3</div><div>part4</div>
如果我们仅仅想拿到标签⾥⾯的内容,就可以使⽤零宽断⾔:
(?<=<div>).*(?=</div>)此时匹配到:part1</div><div>part2</div><div>part3</div><div>part4
结合上⾯的零宽断⾔:
(?<=<div>).*?(?=</div>)此时匹配到:part1 part2 part3 part4
⼀个开发思路的例⼦
当我们想在语料中查英语冠词the的时候,随⼿写下正则/the/。
但是随后发现有些地⽅是不完善的,⽐如当the出现在开头的时候,就是The,因此我们把正则改成/[tT]he/。
此时这个正则还是不完善的,因为它会到诸如There,other这样的单词,因此我们给它加上了词界/\b[tT]he\b/。
问题⼜来了,假如我们不想把下划线和数字作为词界,我们还希望能够到形如 _the,the99这样的词。此时我们需要给the的两段加上限制:不能为字母。于是正则变成了/[^a-zA-Z][tT]he[^a-zA-Z]/。
万事⼤吉了吗?这时候我们发现,当the出现在开头的时候,正则不到它,因为我们规定了the的开头必须有⼀个⾮英⽂字符,因此我们需要修改开头为,the出现在开头或者开头有⼀个⾮英⽂字符。即/(^|[^a-zA-Z])[tT]he[^a-zA-Z]/。
终于到这⾥,⼀个符合要求的简单的定冠词the被搜索了出来。
平时书写正则的时候也要注意,提升准确率,提升覆盖率。
第⼆个例⼦
附上⼀个正则符号表
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论