你来查找,我来定位——正则表达式前后查找

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

哈喽,诸君安!

爬 虫俱乐部以前的推文是不是看过呢?是不是很精彩、很受用?如果是一直关注我们公众号的朋友您一定会发现,在之前的推文中我们介绍的正则表达式都是用来匹配 文本的,但是,文本的位置您是不是也想知道,就告诉我是不是?不多废话,今天小编就引出前后查找(对某一位置的前、后内容进行查找)的概念,给大家分享一 下如何用正则表达式标记要匹配文本的位置(而不仅仅是文本本身)。


前后查找的操作符

正向向前查找

?=

查找出现在被匹配文本之后的字符,但不消费此字符

正向向后查找

?!

查找出现在被匹配文本之前的字符,但不消费此字符

负向向前查找

?<=

向前查找不与给定模式相匹配的文本

负向向后查找

?<!

向后查找不与给定模式相匹配的文本

上表给出了4种前后查找的操作符。我们将给出几个例子来一一解释它们的含义和用法。

正向前后查找

1.正向向前查找

向前查找指定了一个必须匹配但不再结果中返回的模式。向前查找实际上就是一个子表达式,从语法上看,一个向前查找模式其实就是一个以?=开头的子表达式,需要匹配的文本跟在=的后面。有些正则表达式文档使用术语“消费”来表述“匹配和返回文本”的含义。在向前查找里,被匹配的文本不包含在最终返回的匹配结果里,因此被称为“不消费”。

2.正向向后查找

向后查找的操作符为?<=,它表示查找出现在被匹配文本之前的字符(但不消费它)。?<=?=的具体使用方法大同小异:

(1)它必须用在一个子表达式里;

(2)后跟要匹配的文本。

例子说明:

例子1:

clear

set more off

input str25 v

"this is a cat"

end

数据如下:

我们现在需要把单词“is”替换“X”,我们利用ustrregexra()函数进行替换,程序如下:

gen v1 =ustrregexra(v,"is","X")

如上图所示,不仅把单词“is”进行了替换,而且把单词“this”中的“is”替换成了“X”。

在之前的推文中我们介绍了元字符\b,来匹配单词边界,使得结果只匹配到单词“is”。

gen v1 =ustrregexra(v,"\bis\b","X")


事实上,我们还可以通过向后查找来解决这个问题。程序如下:

gen v1 =ustrregexra(v,"(?<= )is","X")


同样,结果中只匹配到了单词“is”。上述文本中,单词“is”前边是一个空格,而单词“this”中的“is”前是“th”。所以我们可以通过向后查找模式,解决这一问题。

子表达式(?<= )为一个向后查找模式,其被用来确定正确的匹配位置,只要找到“空格”就行了,“空格”并不出现在最终的匹配结果里。

在上述文本中,匹配到“空格”之后,再向后搜索“is”,因为“this”中的“is”前是“th”,所以不进行匹配。

例子2:

clear

set more off

input str25 v

"this is an island"

end


我们仍然可以通过元字符\b,来匹配单词边界,来准确匹配到单词“is”。程序如下:

gen v1 =ustrregexra(v,"\bis\b","X")


同样,我们可以通过前后查找来解决这个问题。但是和上边例子不同的是单词“island”中的“is”前也是空格,如果我们按照上述向后查找模式直接进行替换的话,island中的“is”也将被替换成“X”。

gen v1 =ustrregexra(v,"(?<= )is","X")


这个时候,我们就需要用到向前查找模式(?=),通过向前查找模式和向后查找模式的结合解决这个问题。程序如下:

gen v1 =ustrregexra(v,"(?<= )is(?= )","X")


我们看到只有单词“is”得到了替换。

与上述例子的不同的是,我们增加了向前查找模式(?= ),它表示首先匹配“空格”,然后再向前搜索“is”,因为“island”中“is”后是“land”而不是空格,所以不进行匹配。从而结果中只匹配到单词“is”。

例子3:

我们在之前推文字符串函数、正则表达式与变量拆分中,讲到一个拆分变量的例子。数据如下:

clear

input str20 SexAge_Race

MALE41.2_White

FEMALE42.9_White

FEMALE38.5_White

FEMALE35.6_Hispanic

FEMALE48.5_White

end


我们想要把这个数据变成包含SexAgeRace三个变量的形式,所以需要把SexAge_Race这个变量拆分成SexAgeRace三个变量。这里,我们就可以用前后查找来拆分变量SexAge_Race

程序如下:

gen Sex =ustrregexs(0) if ustrregexm(SexAge_Race,".+?(?=\d)")

gen Age =ustrregexs(0) if ustrregexm(SexAge_Race,"[\d\.]+(?=_)")

gen Race =ustrregexs(0) if ustrregexm(SexAge_Race,"(?<=_).+")

结果如下:


提取Sex时,用到正则表达式.+?(?=\d),其中(?=\d)为向前查找模式,(?=\d)匹配到数字但不消费它。 .+?表示懒惰匹配模式,也就是把最左端的数字前面所有的内容提取出来。

提取Age时,用到正则表达式[\d\.]+(?=_),其中(?=_)为向前查找模式,(?=_)匹配但不消费“_”,[\d\.]+匹配至少一次数字或“.”。也就是把_左端的数字和“.”提取出来。

提取Race时,用正则表达式(?<=_).+,其中(?<=_)为向后查找模式,(?<=_)匹配但不消费“_,.+匹配任意字符至少一次。也就是把_右端的内容全部提取出来。

注意:向前查找模式的长度是可变的,它们可以包含.+之类的元字符,所以非常灵活。但是,向后查找模式只能是固定长度。(例如:(?=\d+)是合法的,而(?<=\d+)是非法的)

负向前后查找

负向向前查找的操作符为?!,它表示向前查找不与给定模式相匹配的文本;负向向后查找的操作符为?<!,它表示向后查找不与给定模式相匹配的文本。我们举一个例子,来说明它们的用法。

例子说明:

clear

use d:/example


我们需要从机构地址中,把城市名称提取出来。观察这个数据我们看到,城市的名称要么直接在字符串的开头(如:123610行),要么就跟在安徽省的后边(如:48行),要么就是没有城市名称的信息(如第579行)。我们很容易想到这样的正则表达式:

gen city =ustrregexs(2) if ustrregexm(机构地址,"(安徽省)?(.+?)")


我们看到,第579行并不是我们想要的结果。这3行中中没有城市名称的信息,匹配结果应该是missing。为什么出现这种情况呢?

我们在用(.+?)这个子表达式匹配文本时,会对“市”前边的任意字符进行匹配。因为第57行中存在“市场”这个字符串,而第9行中存在“超市”这个字符串。因此,这三行“市”之前的字符都会进行相应的匹配。这里我们可以利用负向前后查找模式,解决这个问题。

程序如下:

gen city3 =ustrregexs(2) if ustrregexm(机构地址, "(安徽省)?(.+?(?<!))(?!)")


与之前程序相比,我们添加了两个子表达式:(?<!)(?!)

(1)表达式(?<!)为负向向后查找模式,它表示“市”的前一个字符如果是“超”,就不进行匹配,其他的都进行相应的匹配。

(2)表达式(?!)为负向向前查找模式,它表示“市”的后一个字符如果是“场”,就不进行匹配,其他的都进行相应匹配。

这样,通过负向前后查找模式,我们就准确的提取了城市的名称。

以上就是小编今天分享给大家的内容,大家不妨试试吧。此外,小编要悄悄告诉大家一个小秘密:

stata培训哪家强?的搜寻结果

1个回答-

提问时间:2017年1月2日

[最佳回答] 亲爱的stata爱好者,您好。

爬虫俱乐部是一个专注解决stata各种疑难杂症的公众号,深受大家喜爱。该公众号即将举办线下stata培训,技术大牛亲手教你stata,赶紧戳开独家Stata技术培训,千呼万唤始出来报名吧!

EmmaWatson   9999……999条好评


 

 接下来报告空气质量

全国空气质量如下


同情帝都人民!


以上就是今天给大家分享的内容了,说得好就赏个铜板呗!有钱的捧个钱场,有人的捧个人场~,点赞打赏随您心意,么么哒~

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


编辑 by张欢



往期推文推荐:

1.独家Stata技术培训,千呼万唤始出来

2.关于RTF你不知道的命令

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的数据处理和分析技巧。

投稿邮箱:xueyuan19920310@163.com

投稿要求:

1)必须原创,禁止抄袭;

2)必须准确,详细,有例子,有截图;

注意事项:

1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。

2)邮件请注明投稿,邮件名称为“投稿”+“推文名称”。

3)应广大读者要求,现开通有偿问答服务,如果大家遇到关于stata分析数据的问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。


欢迎关注爬虫俱乐部

微信扫一扫
关注该公众号