我正在学习Pig Latin并使用正则表达式。不确定正则表达式是否与语言无关,但这是我正在尝试做的事情。
如果我有一个包含两个字段的表:tweet id和tweet,我想查看每条推文并提取所有提及最多3个。
因此,如果推文上的内容类似于“@tim bla @sam @joe something bla bla”那么该推文的订单项将包含推文ID,时间,山姆,乔。
原始数据有twitter ID而不是实际句柄所以这个正则表达式似乎返回提及(.*)@user_(\\S{8})([:| ])(.*)
以下是我的尝试:
a = load 'data.txt' AS (id:chararray, tweet:chararray);
b = foreach a generate id, LOWER(tweet) as tweet;
// filter data so only tweets with mentions
c = FILTER b BY tweet MATCHES '(.*)@user_(\\S{8})([:| ])(.*)';
// try to pull out the mentions.
d = foreach c generate id,
REGEX_EXTRACT(tweet, '((.*)@user_(\\S{8})([:| ])(.*)){1}',3) as mention1,
REGEX_EXTRACT(tweet, '((.*)@user_(\\S{8})([:| ])(.*)){1,2}',3) as mention2,
REGEX_EXTRACT(tweet, '((.*)@user_(\\S{8})([:| ])(.*)){2,3}',3) as mention3;
e = limit d 20;
dump e;
所以在那次尝试我尝试使用量词,尝试在推文{1},{1,2},{2,3}中返回匹配的第一,第二和第三个实例。
这不起作用,提到1-3只是空的。
所以我尝试改变d:
d = foreach c generate id,
REGEX_EXTRACT(tweet, '(.*)@user_(\\S{8})([:| ])(.*)',2) as mention1,
REGEX_EXTRACT(tweet, '(.*)@user_(\\S{8})([:| ])(.*)@user_(\\S{8})([:| ])(.*)',5) as mention2,
REGEX_EXTRACT(tweet, '(.*)@user_(\\S{8})([:| ])(.*)@user_(\\S{8})([:| ])(.*)@user_(\\S{8})([:| ])(.*)',8) as mention3,
但是,不是返回提到的每个用户,而是返回相同的提及3次。我曾经预料到,通过再次粘贴表达式,我将获得第二场比赛,并且第三次将其粘贴将获得第三场比赛。
我不确定我是如何设法说出这个问题的,但换句话说,假设函数regex_extract()返回了一系列匹配的术语。我想提一下[0],提及[1],在单个项目中提及[2]。
答案 0 :(得分:2)
无论何时使用PATTERN_EXTRACT或PATTERN_EXTRACT_ALL udf,请记住它只是由Java处理的纯正则表达式。
通过本地Java测试更容易测试正则表达式。这是我发现可接受的正则表达式:
Pattern p = Pattern.compile("@(\\S+).*?(?:@(\\S+)(?:.*?@(\\S+))?)?");
String input = "So if a tweet goes something like @tim bla @sam @joe @bill something bla bla";
Matcher m = p.matcher(input);
if(m.find()){
for(int i=0; i<=m.groupCount(); i++){
System.out.println(i + " -> " + m.group(i));
}
}
有了这个正则表达式,如果至少有一个提及,它将返回三个字段,如果找不到第二个/第三个提及,则秒和/或第三个为空。
因此,您可以使用以下PIG代码:
d = foreach c generate id, REGEX_EXTRACT_ALL(
tweet, '@(\\S+).*?(?:@(\\S+)(?:.*?@(\\S+))?)?');
您甚至不需要先过滤数据。