2013-05-22 40 views
0

这是我的Hadoop工作:awk不Hadoop中的映射工作

hadoop streaming \ 
-D mapred.map.tasks=1\ 
-D mapred.reduce.tasks=1\ 
-mapper "awk '{if(\$0<3)print}'" \ # doesn't work 
-reducer "cat" \ 
-input "/user/***/input/" \ 
-output "/user/***/out/" 

此作业总是失败,有一个错误说:

sh: -c: line 0: syntax error near unexpected token `(' 
sh: -c: line 0: `export TMPDIR='..../work/tmp'; /bin/awk { if ($0 < 3) print } ' 

但是,如果我改变-mapper成这样: -mapper“awk”{print}'“ 它没有任何错误。 if(..)有什么问题?

更新:

感谢@paxdiablo为您的详细解答。

在将输入数据传输到我的自定义bin之前,我真正想要做的是过滤掉第一列大于x的一些数据。所以-mapper实际上看起来像这样:

-mapper "awk -v x=$x{if($0<x)print} | ./bin" 

有没有其他方法可以实现这一目标?

+0

顺便提一下,Alcott'$ 0'是整个输入行。如果你只想要第一个字段,那就是$ 1。 – paxdiablo

回答

1

该问题与if本身不符,这是因为您的命令中的引号已从您的awk命令中删除。

,当你在错误输出你会认识到这一点:

sh: -c: line 0: `export TMPDIR='..../work/tmp'; /bin/awk { if ($0 < 3) print } ' 

,当您尝试执行直接在报价剥命令:

pax> echo hello | awk {if($0<3)print} 
bash: syntax error near unexpected token `(' 

pax> echo hello | awk {print} 
hello 

的原因{print}一个作品是因为它不包含外壳特殊的(字符。你可能想尝试

一件事是逃跑的特殊字符,以保证外壳不会试图解释它们:

{if\(\$0\<3\)print} 

这可能需要一些努力得到正确转义字符串,但你可以查看错误输出以查看生成的内容。我不得不逃脱(),因为它们是shell子shell创建命令,$防止可变扩展,而<防止输入重定向。


还铭记保持,有可能是其他的方式取决于筛选你的需求,就是能够避免壳特殊字符的方式。如果您指定了您的需求,我们可以进一步提供帮助。

例如,您可以创建一个shell脚本(如pax.sh)为你做的实际awk工作:

#!/bin/bash 
awk -v x=$1 'if($1<x){print}' 

然后使用shell脚本映射器中没有任何特殊的shell字符:

hadoop streaming \ 
    -D mapred.map.tasks=1 -D mapred.reduce.tasks=1 \ 
    -mapper "pax.sh 3" -reducer "cat" \ 
    -input "/user/***/input/" -output "/user/***/out/" 
+0

是的,你是对的,但有什么办法解决它? – Alcott

+0

谢谢,我已经更新了我的帖子,增加了我的真正目的。 – Alcott

+0

@Alcott,我添加了一个可能使其可行的可能性。查看更新后的答案。 – paxdiablo