PerlでHadoopのMap-Reduceを書く

Hadoop Streaming - naoyaのはてなダイアリー

最初Rubyで書いたけど、なれないことで悩みたくなかったのでとりあえずPerl
例示は、ありがちな「単語の数を数える」

サンプル

処理対象のデータ

$ cat data

aaa bbb ccc ddd
eee fff ggg hhh
aaa bbb ccc ddd

プログラム

$ cat mapper.pl

#!/usr/bin/env perl

# mapper.pl

use strict;  
use warnings;

while (<>) {  
  chomp;  
  my @fields = split /[\s\r\n]+/;

  foreach my $word ( @fields ) {  
    printf "%s\t%s\n", $word, 1;  
  }  
}

$ cat reducer.pl

#!/usr/bin/env perl

# reducer.pl

use strict;  
use warnings;

while (<>) {  
  chomp;  
  my @fields = split /[\s\r\n]+/;

  foreach my $word ( @fields ) {  
    printf "%s\t%s\n", $word, 1;  
  }  
}

面倒なので実行用のShellスクリプト

$ cat doHadoop.sh
#!/bin/sh

# 結果のディレクトリを初期化する  
echo "upload data file"  
hadoop dfs -put $1 $1

echo "delete output dir"  
hadoop dfs -rmr $2

echo "start hadoop"  
time hadoop jar /usr/local/hadoop/contrib/streaming/hadoop-streaming-0.20.203.0.jar -input $1 -output $2 -mapper $3 -reducer $4

hadoop dfs -get $2/part-00000 part-00000

動かしてみる

$ ./doHadoop.sh data out /path/to/mapper.pl /path/to/reducer.pl
$ cat part-00000
eee 1
hhh 1
ggg 1
bbb 2
fff 1
aaa 2
ccc 2
ddd 2

※ mapperとreducerはフルパスで書かないと怒られるっぽい