美文网首页
快速入门|用正则表达式提取数据实例一则

快速入门|用正则表达式提取数据实例一则

作者: Kaidi_G | 来源:发表于2020-01-16 06:11 被阅读0次

推荐小白打开 此文 进行粗泛阅读,并打开这个cheat sheet在一边当作字典查询。
使用https://regex101.com/在线审阅自己的答案是否正确。

相信点开这篇文章的同学都已经知道正则表达式是用来从海量数据中匹配出自己需要的信息的,
本文以下列数据为样本进行信息提取,来进行最基础/常用的正则表达式训练,请拷贝到上文链接中的Test string文本框中开始进行你的初次练习吧~

2018-11-17 01:08:43,364 [DEBUG   ] NATP: <GCF  000761 TS_10_0489943484>CALL GDM:4166 System_LogMessage log_string='Arbitration - Intent:INTENT_CLOUD; Confidence:6712; Domain: DOMAIN_CLOUD; Topic: Calling.Dial; Group: cfv_Phone_Contact; Command: cfv_Phone_Contact_Home; Favorites: False; Slots: {(CONTACTORTHO:lee Evans,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Corey Lawson,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Ford Pete,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Hughes Maurice,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Maurice Hughes,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Pete Ford,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Pete Gabriel,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Pete Louie,LOCATIONREFERENCE:home,CONF:666),(CONTACTORTHO:Pete Walter,LOCATIONREFERENCE:home,CONF:666)}';
2018-11-17 01:06:33,344 [DEBUG   ] NATP: <GCF  000254 TS_10_04666668>CTRL INFO ARTT MSG='===TC - END=== TestCase: <Accuracy_ENU_id_004_setup_config_eco> - id: <Accuracy_ENU_id_666> -  (memory monitor: 0, running folder: c:\\jenkins\\workspace\\GM\\test\\ARTT)';
2018-11-17 01:06:36,257 [DEBUG   ] NATP: <GCF  000258 TS_10_0666660>CTRL INFO ARTT MSG='===TC - START=== TestCase: <Accuracy_ENU_id_801_setup_restart_artt> - id: <Accuracy_ENU_id_801> -  (memory monitor: 0, running folder: c:\\jenkins\\workspace\\GM\\auto-ps-qa-fw\\test\\ARTT_testsuite_MY19)';
2018-11-17 01:06:36,263 [DEBUG   ] NATP: <GCF  000115 TS_10_66666>CTRL INFO ARTT MSG='Initialize Test : Accuracy_ENU_id_666_setup_restart_artt (Flow)';
2018-11-17 01:06:36,588 [DEBUG   ] NATP: <GCF  000044 TS_10_0489816718>CTRL INFO ARTT MSG='Sending EVENT : PTT...';
2018-11-17 01:08:43,364 [DEBUG   ] NATP: <GCF  666661 TS_10_066666>CALL GDM:6666 System_LogMessage log_string='Arbitration - Intent:INTENT_CLOUD; Confidence:6666; Domain: DOMAIN_CLOUD; Topic: Calling.Dial; Group: cfv_Phone_Contact; Command: cfv_Phone_Contact_Home; Favorites: False; Slots: {(CONTACTORTHO:Corey Foster,LOCATIONREFERENCE:home,CONF:666),


需求为:
1.请找到这份log文件中所有的Arbitration行,并提取 date, domain
2.提取slots中所有不姓和名都不为Pete的人

解决这个任务的核心就是:写一个正则表达式,使其能逻辑上和你的目标行匹配,且只和你的目标行匹配。也就是说,你要把你的目标行转化为正则语言。


1.

逻辑分析:

  • 本log有6行,每行之间有换行符,行结构有规律。
  • Arbitration行会有含有“Arbitration”这个单词,我们需要从这些行中提取行最开头的日期和 Domain: 后面的值;
  • 日期的格式为 2020-00-00在行头,可有规律的定义为【四个数字一个-两个数字一个-两个数字】,也可有规律的定义为【从行头开始直到第一个空格为止的内容】
  • Domain信息可有规律的定义为【Domain:之后直到遇到第一个;为止的内容】

查阅文章开头给的cheat sheet,发现在Regex里,\d表示为一个数字,{n}表示为前面的字符重复n次。
也就是说形似2020-00-00的所有字符串都可以用【\d{4}-\d{2}-\d{2}】的正则语言来表述。【\d{4}-\d{2}-\d{2}】就是【四个数字一个-两个数字一个-两个数字】的正则表达。

//这里用一个小括号()把我们的日期正则表达式括起来,括号可以理解为 括起来的信息是我要提取的一部分
括号里面的内容被叫做group,如下图右侧显示的,full match是整句正则匹配到的范围,group表示的是我们要专门提取的信息的部分。

日期匹配

继续往下读,接下来的字符我们都不感兴趣,因为唯一能确定这一行是我们需要行的定位词为Arbitration。
所以,接下来的逻辑为【跳过所有字符直到发现Arbitration】。
查阅cheat sheet,发现.代表任意字符,* 代表前一个字符重复0或任意次,而?代表向后greedy查询,意即找到第一个目标就停下。
也就是说【跳过所有字符直到发现Arbitration】写作正则表达就是【.*?Arbitration】。

//注意,这里的?是可要可不要的,因为我们的目标行里面有且只有一个Arbitration,所以并不必须规定找到第一个Arbitration就停下。

//如果在第一步开头加上 ^ 符号运算效率会大大提升,因为 ^ 符号表示从行头开始匹配,意即这个正则表达式只会从每一行开头寻找数字,省去了从文件中间寻找数字的步骤。但这只适用于本例,如果你的原始数据是一整行没有回车符的话就不起作用了。

image.png

再继续往下读,我们只需要提取Domain后面的信息即可。
同上一步一样跳跃过中间不需要的字符知道我们发现Domain:,可以写作【.?Domain:】
接下来观察发现我们需要的信息格式为【空格后直到第一个;之间】
可以写作【\s(.
?);】
\s 表示的是一个空格,我们需要提取的信息就是括号里面的 .*?; 意即,任何字符重复任何次数直到;
注意这里不要把;放到括号里面了,因为我们的数据并不需要这个分号。
汇总后,第一个问题的答案如下:

^(\d{4}-\d{2}-\d{2}).*?Arbitration.*?Domain:\s(.*?);

两条匹配,group1为我们的日期,group2为我们的Domain信息。


Task1

2.

括号还有一个更基本的含义,就是把括号内的内容视为一个整体后面跟的操作符将会对整个括号起效。如【C(AB)*】可以匹配到【CABABAB】

  • 人名从CONTACTORTHO:开始到逗号,结束
  • 我们需要的中间内容的核心为“不含Pete”
  • 【不含Pete】的正则表达为【(?!Pete)】
  • 需要捕获的内容逻辑转换为:【一个不含Pete的字符串循环1或任意次数】,正则表达为【((?!Pete).)+】

// 这里用 + 而不是 * 因为逻辑上人名不应该为空,换成 * 对结果无影响

不过这里有一个问题,我们用了一个括号(),但是这个括号的内容(?!Laurie). 并不是我们想要捕获的group,只是我们用来使用操作符的。
所以为了忽略这个我们并不需要的group,这里要用到(?: )
查看cheat sheet可知,(?: )为 非捕获组(Non-capturing group)
意即,这个符号里面的group不会被捕获到。
所以,回到我们的问题,我们需要补获的内容【一个不含Laurie的字符串循环1或任意次数】加上正确的group和non-captureing group后就是【((?:(?!Pete).)+?),】
汇总后,第二题的答案如下:

CONTACTORTHO:((?:(?!Pete).)+?),

注意我们已经过滤掉了 Ford Pete 和 Pete Ford


Task 2

下面再提供两种它解,试试看在结果上和运行速度上有什么不同,并思考一下如何提高效率。

CONTACTORTHO:((?!([\w\s]+)?Pete)[\w\s]+)
CONTACTORTHO:(?!(?:[\w\s]+)?Pete)([\w\s]+)

相关文章

网友评论

      本文标题:快速入门|用正则表达式提取数据实例一则

      本文链接:https://www.haomeiwen.com/subject/rhnxzctx.html