2013-05-22 2 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(..)?

UPDATE:

Спасибо @paxdiablo за подробный ответ.

то, что я действительно хочу сделать, это отфильтровать некоторые данные, чей 1-й столбец больше x, перед тем, как направить входные данные в мой пользовательский bin. Так что на самом деле -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} 

Это может занять некоторое усилие, чтобы получить правильно сбежавшую строку, но вы можете посмотрите на вывод ошибки, чтобы увидеть, что генерируется. Мне пришлось избегать (), так как они представляют собой команды создания оболочки оболочки, $ для предотвращения расширения переменных и < для предотвращения перенаправления ввода.


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

Например, вы можете создать скрипт (например, pax.sh), чтобы сделать фактическую awk работу за вас:

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

затем использовать этот скрипт в картографа без каких-либо специальных символов оболочки:

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

Смежные вопросы