正则表达式为 return 所有值,而不仅仅是第一个找到的值

regex to return all values not just first found one

我正在学习 Pig Latin 并且正在使用正则表达式。不确定正则表达式是否与语言无关,但这是我正在尝试做的。

如果我有一个包含两个字段的 table:tweet id 和 tweet,我想遍历每条 tweet 并提取所有提到的最多 3 个。

因此,如果一条推文类似于“@tim bla @sam @joe something bla bla”,那么该推文的行项目将具有推文 ID、tim、sam、joe。

原始数据包含推特 ID 而不是实际句柄,因此此正则表达式似乎 return 提及 (.*)@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;

所以在那次尝试中我在玩量词,试图 return 推文中匹配的第一个、第二个和第三个实例 {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,

但是,不是 return 提及每个用户,而是 return 对同一个提及进行了 3 次。我原以为通过再次剪切 n 粘贴表达式我会得到第二个匹配项,第三次粘贴它会得到第三个匹配项。

我不确定我对这个问题的表述有多好,但换句话说,假设函数 regex_extract() return 编辑了一组匹配的术语。我想在单个订单项上提及[0]、提及[1]、提及[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));
    }
}

使用此正则表达式,如果至少有提及,它将 returns 三个字段,如果未找到 second/third 提及,则秒数 and/or 第三个为空。

因此,您可以使用以下 PIG 代码:

d = foreach c generate id, REGEX_EXTRACT_ALL(
         tweet, '@(\S+).*?(?:@(\S+)(?:.*?@(\S+))?)?');

您甚至不需要先过滤数据。