улей regexp_extract странность - PullRequest
       12

улей regexp_extract странность

11 голосов
/ 14 декабря 2011

У меня проблемы с regexp_extract:

Я запрашиваю файл с разделителями табуляции, столбец, который я проверяю, содержит строки, которые выглядят следующим образом:

abc.def.ghi

Теперь, если я сделаю:

select distinct regexp_extract(name, '[^.]+', 0) from dummy;

Работа MR запускается, она работает, и я получаю "abc" из индекса 0.

Но теперь, если я хочу получить "def" из индекса 1:

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

Я что-то здесь не так делаю?

Спасибо, Mario

Ответы [ 2 ]

33 голосов
/ 14 декабря 2011

Из документов 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)

редактировать

Меня снова заинтересовало это, просто к вашему сведению, для вас может быть ярлык / обходной путь.

Похоже, вы хотите, чтобы определенный сегмент был отделен точкой ., что почти похоже на разделение.
Более чем вероятно, что используемый механизм регулярных выражений перезаписывает группу, если она определяется количественно более одного раза.
Вы можете воспользоваться этим примерно так:

Возвращает первый сегмент: 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).

и он все еще возвращает буфер захвата 1 после {N} -ой итерации.

Вот оно разбито

^                # 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 голос
/ 14 декабря 2011

Я думаю, что вы должны сделать 'группы' нет?

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

(не проверено)

Я думаю, что это ведет себя как библиотека Java, и это должно работать, дайте мне знать, хотя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...