最近項目中需要一個時間段的數據作爲輸入到 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。