読者です 読者をやめる 読者になる 読者になる

About connecting the dots.

statistics/machine learning adversaria.

セミコロンに関するPigの既知のバグ

問題:セミコロンをパースできない

PigにはSTRSPRITという,区切り文字で文字列を分割する関数があります.PHPでいうところのexplode()みたいなもんですね.Pigでは改行文字として";"を使ってるんですが,このセミコロンを区切り文字にしてしまうと,以下のようにエラーが出てしまいます.

> DUMP data:

(id0001,item1;item2;item3)

> m = FOREACH data GENERATE STRSPLIT($1, ';', 10);

ERROR 1000: Error during parsing. Lexical error at line 1, column 41.  Encountered: <EOF> after : "\";"

これは要するに,Pigのパーサが構文を解析する際に,改行文字を正しくエスケープした形で処理してくれていないからで,要するに既知のバグなわけです.少なくとも,CDH3系統のPigでは大体どれでもこのエラーが出てしまうみたいですね.これ以外にも,REGEX_EXTRACTやREGEX_EXTRACT_ALLで正規表現内にセミコロンを用いた場合にも,同様のエラーが生じてしまうようです.この問題への対応法は,大きく分けて2つあります.

解決策その1:セミコロンをUnicode記法で表す

セミコロンをUnicodeで表すと,"\\u003B"になります.先ほどの例で,区切り文字をこれにしてしまえば,上記エラーは生じなくなります.具体的には,以下の書き方をすればOKです.ちなみに,囲み文字はシングルクォートでなければいけません.ダブルクォートにするとこけます.

> m = FOREACH data GENERATE STRSPLIT($1, '\\u003B', 10);

解決策その2:foreach文で囲む

おそらく,{}を先にパースして,その中で適切なエスケープ処理をするからなのでしょうけど,FOREACH GENERATEで{}で囲んだ形にしてしまえば,今度は通常のセミコロンの書き方でもOKだったりします.あ,この場合でもシングルクォートでなければだめなのは同じです.

> m = FOREACH data {
>     splited = STRSPLIT($1, ';');
>     GENERATE splited;
> }

Pigって基本的にエラーメッセージがえらく不親切なので,こういう細かい躓きについて,原因を特定するのが大変なんですよね...

参考:piglatin - Pig problem with split string(STRSPLIT) - Stack Overflow