最近项目中需要一个时间段的数据作为输入到 Mapreduce 处理,比如时间段20190410 - 20190510 这样一个月的数据。以下是我的解决办法,可能有更好的方式,欢迎大家留言。
首先回顾一下 hadoop streaming 的通配符:
通配符 | 名称 | 匹配 |
---|---|---|
* | 星号 | 匹配0或者多个字符 |
? | 问号 | 匹配单一字符 |
[ab] | 字符类别 | 匹配{a,b} 中的一个字符 |
[ ^ab ] | 非字符类别 | 匹配不是{a,b} 中的一个字符 |
[a-b] | 字符范围 | 匹配一个在{a,b} 范围内的包括ab, a<=b |
[ ^a-b ] | 非字符范围 | 匹配一个不在{a,b} 范围内的包括ab, a<=b |
{ a, b } | 或选择 | 匹配包含a或b 的一个语句 |
\c | 转义字符 | 匹配元字符c |
在看一下 常见的 hadoop streaming 的执行脚本
$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper myPythonScript_mapper.py \
-reducer myPythonScript_reducer.py \
-file myPythonScript_mapper.py \
-file myPythonScript_reducer.py
这里的input 就是需要定义的输入,但是只通过上面的通配符(正则表达式不支持)我们没有办法实现输入这样一个时间的数据。
通过研究发现 -input myInputDirs 这个参数可以输入多个路径,也就是可以
-input myInputDirs_1,myInputDirs_2,myInputDirs_3,...
之间通过"," 连接不能有空格。所以抛弃原来的通配符,我们需要将所有的路径拼接然后左右 -input 的参数。
现在有另一个问题了,20190410-20180510 中间跨了一个月,虽然可以写代码确认现在是哪个月,有多少天,但是对于一个shell 执行脚本,显然太复杂了。
这个时候就要借用时间戳(Unix timestamp )来解决这个问题。一天的时间就是86400秒
脚本运行命令如下:
./get_data.sh 20190410 20190510
时间输入的格式也可以是 2019-04-10, 可以识别的时间格式挺多的,我没有深入研究。 如果只是当天也不需要详细到时分秒,默认是2019-04-10 00:00:00。
下面就是./get_data.sh 的内容
#!/bin/sh
hadoop_home=/data/home/hadoop
start_time=$1
end_time=$2
if [ ! -n "$1"] || [ ! -n "$2" ]; then
echo "Please input para !"
else
start_timestamp=$( date -d "$start_time" +%s)
end_timestamp=$( date -d "$end_time" +%s)
input=/data_of_hive_path/$start_time/part-*
for((i=$start_timestamp+86400; i <= $end_timestamp; i+=86400))
do
cur_time=$(date -d "@$i" +%Y%m%d)
str=/data_of_hive_path/$cur_time/part-*
input=$input','$str
done
fi
echo $input
这样就可以获取了我们想要的input。