正则表达式为 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+))?)?');
您甚至不需要先过滤数据。
我正在学习 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+))?)?');
您甚至不需要先过滤数据。