セミコロンに関する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