2013-12-22 4 views
2

Непосредственного вопрос, это просто трудна Google регулярок синтаксиса ...Java/Hive интерпретация регулярных выражений

Я иду через HortonWorks Hive tutorials (Hive использует то же регулярное выражение в Java), и следующий ЗЕЬЕСТ использует регулярное выражение, чтобы вытащить от того, что, вероятно, данные в формате JSON ...

 INSERT OVERWRITE TABLE batting 
     SELECT 
     regexp_extract(col_value,'^(?:([^,]*)\.?){1}',1) player_id, 
     regexp_extract(col_value,'^(?:([^,]*)\.?){2}',1) year, 
     regexp_extract(col_value,'^(?:([^,]*)\.?){9}',1) run 
     FROM temp_batting; 

данные выглядит следующим образом:

PlayerID, yearID, скупились, TeamID, lgID, G, G_batting, AB, R, H, 2B, 3B, HR , RBI, SB, CS, BB, SO, IBB, HBP, SH, SF, GIDP, G_old aardsda01,2004,1, SFN, NL, 11,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11 aardsda01,2006,1, CHN, NL, 45,43,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,45 aardsda01,2007,1, CHA, AL, 25, 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2

И поэтому PlayerID находится в столбце1, год - столбец2, R (работает) - это столбец 9. Как regexp_extract успешно извлекает эти данные?

Я новичок в группах, не связанных с захватом, но мне кажется, что все это не захватывающая группа. Кроме того, я привык видеть {1}, {2} или {9} в форме [0-9] {9}, что соответствует девятизначному числу. В этом случае похоже, что это указывает на 9-й матч чего-то, что называется этим синтаксисом?

ответ

5

Первый перерыв врозь регулярное выражение:

^(?:([^,]*)\.?){n} 
  • ^ является началом String
  • (?:...){n} не является захват группы повторяется n раз
  • ([^,]*) является инвертированный символьный класс, он совпадений "не ," ноль или более раз
  • \.? является необязательным (литералом) .

Итак, как это работает?

Группа, не участвующая в съемке, предназначена исключительно для numeric quantifier, то есть делает весь шаблон в группе повторением n раз.

Фактический захваченный образец находится в группе захвата ([^,]*). Я не уверен, почему есть необязательный ., и я не вижу никаких входов, заканчивающихся . в ваших данных образца, но я предполагаю, что есть некоторые.

Что происходит, когда группа захватывается n раз, но сохраняется только последний захват, который хранится в первой группе, то есть группе 1. Это значение по умолчанию указано в regexp_extract.

Итак, когда образец повторяется один раз в первом случае, мы захватываем первый элемент в массиве, разделенном запятой. Когда образец повторяется дважды во втором примере, мы фиксируем второй элемент. Когда образец повторяется девять раз, девятый элемент захватывается.

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

Было бы лучше, чтобы либо сделать [^,]* притяжательные, добавив +:

^(?:([^,]*+)\.?){n} 

Или сделать все, не захватив группу атомное:

^(?>([^,]*)\.?){n} 
+0

Первый, удивительный ответ, спасибо. Пара вопросов: я не вижу числовой квантификатор {n} на странице, которую вы связали. Я вижу, что он используется в способе [0-9] {n}, но это другой случай, когда он соответствует тому, что находится между скобкой n раз. В этом случае есть круглые скобки, и вместо того, чтобы сопоставлять n прямых раз, похоже, что он говорит только о сохранении n-го совпадения. ?? Во-вторых, в чем смысл добавления начального ^? В данных нет пробелов, поэтому мне кажется, что все начинается с строки. В-третьих, что делает * + в вашей коррекции? Раньше этого не видел. – user1956609

+1

@ user1956609 '{n}' повторяет предыдущий шаблон_ 'n' раз - не имеет значения, является ли его' [] 'или'() '- разница в том, что' [] 'является единственным символом, а'() 'is группировка шаблонов. Прочтите мое объяснение этого соответствия, так как группа _inside_ повторяет шаблон только для совпадения _last_. Наконец, добавление '+' к квантификатору делает его [притяжательным] (http://www.regular-expressions.info/possessive.html). –

0

Я считаю, что это хороший способ практика и обучение regex находится на этом сайте: http://www.regexr.com/

Просто вставьте свое выражение там и удалите/замените детали из этого. Все будет немного лучше, чем пытаться расшифровать регулярное выражение.

0

Другой способ сделать это без использования регулярных выражений заключается в использовании функция разделения

select split('aardsda01,2006,1,CHN,NL,45,43,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,45',',')[0] as player_id, 
split('aardsda01,2006,1,CHN,NL,45,43,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,45',',')[1] as year, 
split('aardsda01,2006,1,CHN,NL,45,43,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,45',',')[1] as runs 
Смежные вопросы