使用shell+awk完成Hive查询结果格式化输出
2014-05-20 15:44
1686 查看
好久不写,一方面是工作原因,有些东西没发直接发,另外的也是习惯给丢了,内因所致。今天是个好日子,走起!
btw,实际上这种格式化输出应该不只限于某一种需求,差不多是通用的。
需求:
--基本的:当前Hive查询结果存在数据与表头无法对齐的情况,不便于监控人员直接查看,或者导出到excel中,需要提供一个脚本,将查询结果处理下,便于后续的查看或者操作。
--额外的:A、每次查询出来的结果字段数、字段长度不固定;B、每个数据文件中可能包含不只一套查询结果,即存在多个schema。
想法:
对于基本需求而言,无非就是将数据文件用格式化输出整理一下,直接想到了awk。
对于补充的情况,A:需要实现一种机制,基于数据文件,动态地确定格式化输出的参数:字段个数,以及每个格式化字符串的长度参数;B:实现对数据文件根据字段数切割成多段,然后对于每段数据套用前面的脚本处理。
做法:
基本需求:
1、指定字段分隔符为“\t”
2、将每个字段按照指定长度格式化输出
额外需求A:
需要把代码写成“活”的,适应各种不同的数据文件,如前面所说,实际上就是在执行格式化输出之前,将数据文件扫描一遍,用一个数组记录下文件中每个字段的max length,然后将这个max length作为该文件内格式化输出的额定宽度。
1、初始化一个fieldLen数组
2、扫描整个文件,更新fieldLen数组
3、将fieldLen数组,用于格式化输出
这里要注意的是,fieldLen的初始化要在NR==1的时候,在BEGIN里面,NF为0
额外需求B:
这里需要一些临时变量,标记分割出来的数据块分支:suffix标记不同的分支,fields当前处理数据块的字段数
处理过程根据前面的临时变量,完成数据文件分割。此处有一个局限在于,对于文件内的多个数据分块,只能处理“AAABBBCCC”这样,同一类数据放在一起的,脚本会分成3块;而对于“AABCABBCC”这种的,则会分割成6块。
基本的思路,就如上面所示。
但是,完成上面的部分,可能不到一半的工作量,接下来,说几个比较麻烦的问题:
A、汉字的问题
这个也是对不齐的主要原因。
在putty里面显示的时候,一个汉字占2个字宽,一个ASCII字符占一个字宽。但是,在调用awk内置的length()函数时,一个汉字跟一个ASCII字符长度是一样的。所以为了在putty上看到的内容是对齐的,需要在格式化输出的时候,对fieldLen的值进行修正。
例子如:
execFormat.awk
btw,实际上这种格式化输出应该不只限于某一种需求,差不多是通用的。
需求:
--基本的:当前Hive查询结果存在数据与表头无法对齐的情况,不便于监控人员直接查看,或者导出到excel中,需要提供一个脚本,将查询结果处理下,便于后续的查看或者操作。
--额外的:A、每次查询出来的结果字段数、字段长度不固定;B、每个数据文件中可能包含不只一套查询结果,即存在多个schema。
想法:
对于基本需求而言,无非就是将数据文件用格式化输出整理一下,直接想到了awk。
对于补充的情况,A:需要实现一种机制,基于数据文件,动态地确定格式化输出的参数:字段个数,以及每个格式化字符串的长度参数;B:实现对数据文件根据字段数切割成多段,然后对于每段数据套用前面的脚本处理。
做法:
基本需求:
1、指定字段分隔符为“\t”
2、将每个字段按照指定长度格式化输出
BEGIN{ FS="\t" } { printf "%-"len"s\t",$i }
额外需求A:
需要把代码写成“活”的,适应各种不同的数据文件,如前面所说,实际上就是在执行格式化输出之前,将数据文件扫描一遍,用一个数组记录下文件中每个字段的max length,然后将这个max length作为该文件内格式化输出的额定宽度。
1、初始化一个fieldLen数组
2、扫描整个文件,更新fieldLen数组
3、将fieldLen数组,用于格式化输出
BEGIN{ FS="\t" } NR==1{ for (i=1;i<=NF;i++) fieldLen[i]=0 } { for (i=1;i<=NF;i++) { len=length($i) if (len>fieldLen[i]) { fieldLen[i]=len } } } END{ for (i=1;i<=NF;i++) { printf "%-s",fieldLen[i] if (i<NF) printf "\t" else printf "\n" } }
这里要注意的是,fieldLen的初始化要在NR==1的时候,在BEGIN里面,NF为0
额外需求B:
这里需要一些临时变量,标记分割出来的数据块分支:suffix标记不同的分支,fields当前处理数据块的字段数
处理过程根据前面的临时变量,完成数据文件分割。此处有一个局限在于,对于文件内的多个数据分块,只能处理“AAABBBCCC”这样,同一类数据放在一起的,脚本会分成3块;而对于“AABCABBCC”这种的,则会分割成6块。
BEGIN{ FS="\t" suffix=0 filename=ARGV[1] fields=0 } { if (NF!=fields) { fields=NF suffix+=1 } print $0>filename"."suffix } END{ print suffix }
基本的思路,就如上面所示。
但是,完成上面的部分,可能不到一半的工作量,接下来,说几个比较麻烦的问题:
A、汉字的问题
这个也是对不齐的主要原因。
在putty里面显示的时候,一个汉字占2个字宽,一个ASCII字符占一个字宽。但是,在调用awk内置的length()函数时,一个汉字跟一个ASCII字符长度是一样的。所以为了在putty上看到的内容是对齐的,需要在格式化输出的时候,对fieldLen的值进行修正。
例子如:
#!/usr/bin/awk BEGIN{ FS="\t" } NR==FNR{ for (i=1;i<=NF;i++) fieldLen[i]=$i } NR!=FNR{ for (i=1;i<=NF;i++) { len=0 for (j=1;j<=length($i);j++) if (substr($i,j,1) > "\177") len+=1 printf "%-'"fieldLen[i]-len"'s",$i if (i<NF) printf "\t" else printf "\n" } }
execFormat.awk
相关文章推荐
- 使用shell+awk完成Hive查询结果格式化输出
- 使用shell+awk完成Hive查询结果格式化输出
- plsql学习范例--使用utl_file包将查询结果输出到文件中
- mongodb格式化输出查询结果
- 在AWK中执行命令并使用getline输出全部结果
- 语音识别完成诗句的查询功能,iOS AVSpeechSynthesis语音输出结果的诗歌APP
- SQLSERVER,不使用BCP,把查询结果输出为txt文本文件的存储过程
- spark查询任意字段,并使用dataframe输出结果
- 格式化查询+使用伪列level+使用level和lpad()函数对层次化查询结果进行格式化处理
- 使用For XML与XSL(XSLT)配套快速输出查询结果到Web页面
- 在Spark中使用UDF对HIVE表进行查询,再将查询结果RDD写入另一个HIVE表
- 使用awk格式化输出文本
- mysql使用in查询,按照期望的顺序输出结果
- Java使用apache的开源数据处理框架commons-dbutils完成查询结果集的各种处理输出(8种方式)
- 【Linux】使用sed、awk来完成批量修改配置文件的shell设计
- 使用Java代码执行系统命令/shell命令, 并获取输出结果
- shell使用echo打印输出及printf格式化输出
- 使用CMD命令 输出查询结果
- awk中输出到多个文件及使用Shell中传入的参数
- Oracle使用in关键字查询时,按照条件输出查询结果