2011-12-13 54 views
10

Tôi gặp một số vấn đề với regexp_extract:hive regexp_extract weirdness

tôi truy vấn trên một tập tin phân định theo tab cột Tôi đang kiểm tra có dây mà trông như thế này:

abc.def.ghi 

Bây giờ, nếu tôi làm: công việc

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

MR chạy, nó hoạt động, và tôi nhận được "abc" từ chỉ số 0.

Nhưng n ow, nếu tôi muốn để có được "def" từ chỉ số 1:

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

Hive không thành công với:

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 

tập tin Log nói:

java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row 

Tôi có làm một cái gì đó về cơ bản sai ở đây ?

Cảm ơn, Mario

Trả lời

27

Từ tài liệu https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF có vẻ như regexp_extract() là một bản ghi/trích xuất dòng dữ liệu bạn muốn trích xuất.

Dường như nó hoạt động trên lần tìm thấy đầu tiên (sau đó thoát) trái ngược với toàn cầu. Do đó chỉ mục tham chiếu đến nhóm chụp.

0 = toàn bộ trận đấu
1 = nhóm chụp 1
2 = chụp nhóm 2, vv ...

diễn giải từ hướng dẫn:

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

This returns 'bar'. 

Vì vậy, trong trường hợp của bạn, để nhận văn bản sau dấu chấm, một cái gì đó như thế này có thể hoạt động:
regexp_extract(name, '\.([^.]+)', 1)
hoặc điều này
regexp_extract(name, '[.]([^.]+)', 1)

chỉnh sửa

tôi đã tái quan tâm đến việc này, chỉ cần một FYI, có thể có một phím tắt/workaround cho bạn.

Dường như bạn muốn phân đoạn cụ thể được phân cách bằng dấu chấm . ký tự, gần giống như chia nhỏ.
Công cụ regex của nó nhiều khả năng được sử dụng sẽ ghi đè lên một nhóm nếu nó được định lượng nhiều lần.
Bạn có thể tận dụng điều đó với một cái gì đó như thế này:

Trả về phân đoạn đầu tiên: abc .def.ghi
regexp_extract(name, '^(?:([^.]+)\.?){1}', 1)

Trả về phân khúc thứ hai: abc. def .ghi
regexp_extract(name, '^(?:([^.]+)\.?){2}', 1)

Trả về đoạn thứ ba: abc.def. ghi
regexp_extract(name, '^(?:([^.]+)\.?){3}', 1)

Chỉ mục không thay đổi (vì chỉ mục vẫn tham chiếu đến nhóm chụp 1), chỉ thay đổi lặp lại regex.

Một số lưu ý:

  • regex này ^(?:([^.]+)\.?){n} có vấn đề mặc dù.
    Yêu cầu phải có thứ gì đó giữa các chấm trong phân khúc hoặc regex sẽ không khớp với ....

  • Có thể là ^(?:([^.]*)\.?){n} nhưng điều này sẽ khớp ngay cả khi có ít hơn n-1 chấm,
    bao gồm chuỗi trống. Đây có lẽ không phải là điều mong muốn.

Có cách để làm điều đó không cần văn bản giữa các dấu chấm, nhưng vẫn yêu cầu ít nhất n-1 dấu chấm.
Điều này sử dụng xác nhận lookahead và bộ đệm chụp 2 làm cờ.

^(?:(?!\2)([^.]*)(?:\.|$())){2}, mọi thứ khác đều giống nhau.

Vì vậy, nếu nó sử dụng regex kiểu java thì thao tác này sẽ hoạt động.
regexp_extract(name, '^(?:(?!\2)([^.]*)(?:\.|$())){2}', 1) thay đổi {2} thành bất kỳ 'phân khúc' nào là cần thiết (điều này có phân đoạn 2).

và nó vẫn trả về bộ đệm chụp 1 sau lần lặp thứ {N}.

Ở đây nó được chia nhỏ

^    # 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) 

Nếu nó không làm khẳng định, thì điều này sẽ không hoạt động!

+0

cảm ơn, đó là nó. thời gian để gửi yêu cầu tính năng với hive :-) – Mario

+0

@Mario - Chào mừng bạn. Thêm regex workaround có thể để rút ngắn những thứ lên như một giải pháp. – sln

+0

tôi ước tôi có thể bầu bạn lần thứ hai – Mario

1

Tôi nghĩ rằng bạn cần phải thực hiện 'nhóm' không?

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

(chưa được kiểm tra)

Tôi nghĩ rằng nó hoạt động như các thư viện java và điều này sẽ làm việc, cho tôi biết mặc dù.

+0

ha, lạ, công việc MR chạy với điều đó, nhưng nó vẫn trả về nội dung của chỉ mục 0! – Mario

+0

và tôi vừa thử đá với chỉ số 2 và sau đó thất bại với 2011-12-13 23: 33: 41,377 Bản đồ giai đoạn 1 = 0%, giảm = 0% 2011-12-13 23:34: 01,465 Bản đồ giai đoạn 1 = 100%, giảm = 100% Công việc đã kết thúc = job_201112071152_0074 có lỗi FAILED: Lỗi thực thi, mã trả về 2 từ org.apache.hadoop.hive.ql.exec.MapRedTask một lần nữa .... lạ kỳ lạ .... – Mario