hive regexp_extract古怪

时间:2011-12-13 22:26:05

标签: regex hive

我在使用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

我在这里做了一些根本错误的事情吗?

谢谢, 马里奥

2 个答案:

答案 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库,这应该可行,但请告诉我。