浅谈正则表达式匹配模式(一)—贪婪模式

2017-06-20 司海涛 爬虫俱乐部 爬虫俱乐部

诸君安

又是stata学习时间

今天给大家介绍的是正则表达式

大家快点学起来

从此写程序快人一步


在stata中,正则表达式有两种最常见的匹配模式,分别为:贪婪模式和懒惰模式。正则表达式在字符串处理方面,能大大简化我们的程序,由于篇幅限制,我们将分为两篇推文给大家介绍这两种匹配模式,今天先给大家介绍一下贪婪模式。

在 贪婪模式下,首先看整个字符串是否能与正则表达式匹配,如果匹配不成功,会去掉该字符串中的最后一个字符,并再次尝试匹配,如果匹配还是不成功,那么再去 掉此时的最后一个字符。如果在去掉所有字符后仍然匹配不成功,那么会继续选取从第二个字符开始的整个字符串,重复上述的匹配过程。这个过程会一直重复,直 到发现一个与正则表达式相匹配的字符串,或者全部尝试过后仍然匹配不出任何字符。用“贪婪”这个词,我们也可以形象地把这个模式解释为:首先吃掉所有的字 符,然后一个一个吐出来,直到匹配成功。

在stata中,当使用除“{n}”之外的数量元字符时,会进入正则表达式匹配的贪婪模式。 例如,正则表达式re符合贪婪模式,对字符串“abc”进行匹配。

1、首先对整个字符串“abc”进行匹配;

2、如果匹配不上,去掉最后一个字符“c”,对“ab”进行匹配;

3、如果匹配不上,去掉最后一个字符“b”,对“a”进行匹配;

4、如果匹配不上,将“abc”第一个字符“a”去掉,对“bc”进行匹配;

5、如果匹配不上,去掉最后一个字符“c”,对“b”进行匹配;

6、如果匹配不上,去掉“bc”中的第一个字符“b”,对“c”进行匹配。


下面我们用一个例子来展示一下贪婪模式:

程序如下:

·clear

·set obs 10

·gen v = "A" + "B" * (_n - 1)

·gen v1 = ustrregexs(0) if ustrregexm(v, "AB*")

·gen v2 = ustrregexs(0) if ustrregexm(v, "AB+")

·gen v3 = ustrregexs(0) if ustrregexm(v, "AB?")

·gen v4 = ustrregexs(0) if ustrregexm(v, "AB{1,3}")

·gen v5 = ustrregexs(0) if ustrregexm(v, "AB{3,}")

·list, sep(0)

程序运行结果如下表所示:

首 先,变量v1是正则表达式"AB*"的匹配结果,元字符“*”为数量元字符,它表示匹配前一个字符或子表达式任意次(这里即表示对字符“B”匹配0次或多 次),我们以变量v中第一条观测值“A”和最后一条观测值“ABBBBBBBBB”为例。对于“A”,正则表达式“AB*”首先对整个字符串“A”进行匹 配,匹配成功,这时候事实上对“B”匹配了0次;对于“ABBBBBBBBB”,正则表达式“AB*”首先岁整个字符串“ABBBBBBBBB”进行匹 配,匹配成功,这里对字符“B”匹配了9次。正则表达式“AB*”的匹配结果可以为A、AB、ABB、ABBB、ABBBB...

v2是 正则表达式“AB+”的匹配结果,与“AB*”不同的是这里必须对字符“B”至少匹配一次,因为元字符“+”表示对前一个字符或子表达式匹配一次或多次; 所以对变量v中“A”进行匹配时,首先匹配整个字符串“A”,因为至少对“B”匹配一次,所以匹配不成功。其匹配结果可以为:AB、ABB、ABBB、 ABBBB、ABBBBB...

v3是 正则表达式“AB?”的匹配结果,元字符“?”表示对前一个字符或子表达式匹配0次或1次,我们还以“A”和“ABBBBBBBBB”为例。首先,对于字 符串“A”进行匹配时,首先对整个字符串进行匹配,匹配成功,这时候对字符“B”匹配了0次;对“ABBBBBBBBB”进行匹配时,首先匹配整个字符串 “ABBBBBBBBB”,因为“AB?”的匹配结果只可能是“A”、“AB”,因此匹配不成功,接着在贪婪模式下,首先去掉字符串的最后一个字符 “B”,对“ABBBBBBBB”进行匹配,同样也是匹配不成功,直到去掉最后一个字符变为“AB”时,匹配成功,这时候对字符B匹配了1次,匹配结果为 “AB”。

v4是 正则表达式“AB{1,3}”的匹配结果,元字符“{n1,n2}”表示对前一个字符或子表达式匹配至少n1次,至多n2次。所以在对“A”进行匹配时, 首先,把整个字符串“A”进行匹配,因为至少对字符“B”匹配1次,所以匹配不成功;对于“ABBBBBBBBB”,同样先对整个字符串 “ABBBBBBBBB”进行匹配,由于对字符“B”至多匹配3次,所以匹配不成功,接着按贪婪模式的匹配法则,首先,去掉字符串末尾最后一个字符 “B”,变为“ABBBBBBBB”,仍然匹配不成功,直到去掉字符“B”后变为“ABBB”时,匹配成功,这时候对字符“B”匹配了3次。

变 量v5是正则表达式AB{3,}的匹配结果,元字符{n,}表示对前一个字符或子表达式匹配至少n次(此例中即表示至少匹配3次)。对“A”进行匹配时, 因为至少对字符“B”匹配3次,所以匹配不成功;对于字符串“ABBBBBBBBB”匹配时,首先,匹配整个字符串“ABBBBBBBBB”,匹配成功, 这时候对字符“B”匹配了9次。


但 是我们要注意一点,贪婪模式并不是说我们匹配出的就是整个字符串中所能匹配到的最长的子字符串,我们仔细分析贪婪模式的概念可以发现,它是先尝试匹配整个 字符串,再从结尾处将一个一个字符剔除掉,这一特点有最高的优先权。也就是说在贪婪匹配模式下,匹配出的实际上是从尽可能靠近字符串开头的位置开始的,与 正则表达式相匹配的最长的字符串。我们以下边一个例子为例:

clear

set obs 1

gen str v = "123a4567"

gen v1 = ustrregexs(0) if ustrregexm(v, "\d+")

list

可 以发现,在贪婪模式下匹配的并不是整个字符串中最长的子字符串“4567”,而是以靠近字符串开头位置开始,与正则表达式相匹配的最长字符串“123”。 它的匹配过程为:首先,元字符“\d”是一个特殊元字符,表示0-9任意一个数字,等价于[0-9],正则表达式“\d+”则表示至少1个的连续数字,匹 配时,先匹配整个字符串“123

a4567”,匹配不成功,然后去掉最后一个字符“7”,变为“123a456”,仍然匹配不成功,再去掉最后一个字符“6”...,直到去掉字符“a”,变为“123”,即匹配成功。



以上就是今天给大家分享的内容了,说得好就赏个铜板呗!有钱的捧个钱场,有人的捧个人场~。

应广大粉丝要求,爬虫俱乐部的推文公众号打赏功能可以开发票啦,累计打赏超过1000元我们即可给您开具发票,发票类别为“咨询费”。用心做事,只为做您更贴心的小爬虫。第一批发票已经寄到各位小主的手中,大家快来给小爬虫打赏呀~

                     文字编辑:梅洁瓷傲

技术总编:刘贝贝



往期推文推荐:

1.高校学术大神:你的导师上榜了吗?

2.中国高校财经、管理与综合类期刊灌水排行榜

3.关于RTF你不知道的命令之番外篇

4.免费事件研究,一片片从邮局寄来

5.免费的股价同步性,一片片从邮局寄来

6.Stata叫你回家听音乐了!

7.一言不合就用stata写邮件(Outlook/Foxmail)

8.听说你想知道怎么用stata画地图?

9.I have a Stata, I have a python

10.I have a Stata, I have a Python之二——pdf转word




关于我们

微信公众号“爬虫俱乐部”分享实用的stata命令,欢迎转载、打赏。爬虫俱乐部是由李春涛教授领导下的研究生及本科生组成的大数据分析和数据挖掘团队。

此外,欢迎大家踊跃投稿,介绍一些关于stata的数据处理和分析技巧。

投稿邮箱:statatraining@163.com

投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿”+“推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到关于stata分析数据的问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。

欢迎关注爬虫俱乐部 

微信扫一扫
关注该公众号