我在使用regexp_extract时遇到了一些问题:
我正在查看制表符分隔的文件,我正在检查的列中包含如下所示的字符串:
abc.def.ghi
现在,如果我这样做:
select distinct regexp_extract(name, '[^.]+', 0) from dummy;
MR作业运行,它有效,我从索引0获得“abc”。
但是现在,如果我想从索引1获得“def”:
select distinct regexp_extract(name, '[^.]+', 1) from dummy;
Hive失败了:
2011-12-13 23:17:08,132 Stage-1 map = 0%, reduce = 0%
2011-12-13 23:17:28,265 Stage-1 map = 100%, reduce = 100%
Ended Job = job_201112071152_0071 with errors
FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.MapRedTask
日志文件说:
java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row
我在这里做了一些根本错误的事情吗?
谢谢, 马里奥
答案 0 :(得分:32)
从文档https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF看来,regexp_extract()是您要提取的数据的记录/行提取。
似乎首先找到(然后退出)而不是全局。因此,索引引用捕获组。
0 =整场比赛
1 =捕获组1
2 =捕获组2等...
从手册中解释:
regexp_extract('foothebar', 'foo(.*?)(bar)', 2)
^ ^
groups 1 2
This returns 'bar'.
因此,在你的情况下,要获得点后的文本,这样的事情可能会起作用:
regexp_extract(name, '\.([^.]+)', 1)
或者这个
regexp_extract(name, '[.]([^.]+)', 1)
修改
我对此非常感兴趣,只是一个fyi,可能有一个快捷方式/解决方法。
看起来你想要一个用点.
字符分隔的特定片段,这几乎就像是分裂
如果它被量化不止一次,那么使用的正则表达式引擎很可能会覆盖一个组
你可以利用这样的东西来利用它:
返回第一段:abc
。def.ghi
regexp_extract(name, '^(?:([^.]+)\.?){1}', 1)
返回第二段:abc。def
。ghi
regexp_extract(name, '^(?:([^.]+)\.?){2}', 1)
返回第三段:abc.def。ghi
regexp_extract(name, '^(?:([^.]+)\.?){3}', 1)
索引不会改变(因为索引仍然引用捕获组1),只有正则表达式重复更改。
一些注意事项:
此正则表达式^(?:([^.]+)\.?){n}
存在问题
它要求段中的点之间存在某些内容,或者正则表达式与...
不匹配。
可能是^(?:([^.]*)\.?){n}
,但即使小于n-1点也会匹配,
包括空字符串。这可能是不可取的。
有一种方法可以做到这一点,它不需要点之间的文字,但仍然需要至少n-1点。
这使用先行断言和捕获缓冲区2作为标志。
^(?:(?!\2)([^.]*)(?:\.|$())){2}
,其他一切都是一样的。
所以,如果它使用java风格的正则表达式,那么这应该有效
regexp_extract(name, '^(?:(?!\2)([^.]*)(?:\.|$())){2}', 1)
将{2}更改为需要的任何“细分”(这会执行细分2)。
并且在第{N}次迭代后仍然返回捕获缓冲区1。
这里分解了
^ # Begining of string
(?: # Grouping
(?!\2) # Assertion: Capture buffer 2 is UNDEFINED
( [^.]*) # Capture buffer 1, optional non-dot chars, many times
(?: # Grouping
\. # Dot character
| # or,
$ () # End of string, set capture buffer 2 DEFINED (prevents recursion when end of string)
) # End grouping
){3} # End grouping, repeat group exactly 3 (or N) times (overwrites capture buffer 1 each time)
如果它没有做断言,那么这将不起作用!
答案 1 :(得分:1)
我认为你必须让'团体'没有?
select distinct regexp_extract(name, '([^.]+)', 1) from dummy;
(未测试的)
我认为它的行为类似于java库,这应该可行,但请告诉我。