Regex 蜂巢正则表达式提取古怪

Regex 蜂巢正则表达式提取古怪,regex,hive,Regex,Hive,我在使用regexp\u extract时遇到一些问题: 我正在查询一个以制表符分隔的文件,我正在检查的列包含如下所示的字符串: abc.def.ghi 现在,如果我这样做: select distinct regexp_extract(name, '[^.]+', 0) from dummy; job先生运行,它工作,我从索引0中得到“abc” 但是现在,如果我想从索引1中获取“def”: select distinct regexp_extract(name, '[^.]+', 1) f

我在使用regexp\u extract时遇到一些问题:

我正在查询一个以制表符分隔的文件,我正在检查的列包含如下所示的字符串:

abc.def.ghi
现在,如果我这样做:

select distinct regexp_extract(name, '[^.]+', 0) from dummy;
job先生运行,它工作,我从索引0中得到“abc”

但是现在,如果我想从索引1中获取“def”:

select distinct regexp_extract(name, '[^.]+', 1) from dummy;
配置单元出现以下故障:

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
我在这里犯了什么根本性的错误吗

谢谢,
马里奥

我想你必须让“团体”不

select distinct regexp_extract(name, '([^.]+)', 1) from dummy;
(未经测试)

我认为它的行为类似于java库,但请让我知道,这应该会起作用。

从文档中可以看出,regexp_extract()是您希望提取的数据的记录/行提取

它似乎是针对一个先发现(然后退出)而不是全局的。因此,索引引用捕获组

0=整个匹配
1=捕获组1
2=捕获组2等

从手册中转述:

regexp_extract('foothebar', 'foo(.*?)(bar)', 2)
                                  ^    ^   
               groups             1    2

This returns 'bar'.
因此,在您的情况下,要获得点后的文本,类似这样的内容可能会起作用:
regexp\u extract(名称“\”([^.]+)”,1)

或者这个
regexp_extract(名称“[.]”([^.]+)”,1)

编辑

我对此很感兴趣,仅供参考,这里可能有一条捷径/解决方法供您选择

看起来您希望使用点
字符分隔特定的段,这几乎类似于拆分。
如果对组进行多次量化,则使用的正则表达式引擎很可能会覆盖该组。
您可以通过以下方式利用这一点:

返回第一个段:
abc
.def.ghi
regexp\u摘录(名称,'^(?:([^.]+)\.?){1}',1)

返回第二段:abc.
def
.ghi
regexp\u extract(名称,'^(?:([^.]+)\.?){2}',1)

返回第三段:abc.def.
ghi

regexp\u摘录(名称,'^(?:([^.]+)\.?){3}',1)

索引没有更改(因为索引仍然引用捕获组1),只有regex重复更改

一些注意事项:

  • 这个正则表达式
    ^(?:([^.]+)\.?){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)

如果它不做断言,那么这就行不通了

哈,奇怪,MR作业是用这个运行的,但它仍然返回索引0的内容!我刚刚尝试了索引2,但是失败了,2011-12-13 23:33:41377 Stage-1 map=0%,reduce=0%2011-12-13 23:34:01465 Stage-1 map=100%,reduce=100%结束了Job=Job_201112071152_0074,错误为:执行错误,再次从org.apache.hadoop.hive.ql.exec.MapRedTask返回代码2。。。。怪怪的。。。。