Hive导出csv解密后出现多余制表符导致BigQuery加载失败如何解决
问题1:定位多余制表符+Ansible自动化处理
- 定位异常行方法:正常21列的TSV文件每行应该有20个制表分隔符,执行以下命令直接输出所有列数不符的行:
awk -F'\t' '{if(NF!=21) print "行号:"NR,"实际列数:"NF,"内容:"$0}' /tmp/abc.csv
- 自动化处理方案(Ansible):
编写playbook任务,先校验是否存在异常行,再批量替换字段内部的多余制表符(仅保留前20个作为分隔符,后续制表符全部替换为空格):
--- - name: 处理Hive导出TSV多余制表符问题 hosts: your_host_group tasks: - name: 校验异常行 shell: awk -F'\t' 'BEGIN{err=0} NF!=21{err=1; print NR, NF, $0} END{exit err}' /tmp/abc.csv register: tsv_check_result ignore_errors: true - name: 替换多余制表符(仅存在异常行时执行) shell: sed -i ':a;s/\t/ /21;ta' /tmp/abc.csv when: tsv_check_result.rc != 0
问题2:Beeline导出时添加双引号避免分隔符混乱
可以直接修改beeline导出参数,给所有字段包裹双引号,同时转义字段内部的特殊字符,不需要修改SQL逻辑:
- 你原命令用的是
tsv2格式,修改为如下参数即可:
beeline -u $HIVE_JDBC_URL --silent=true \ --outputformat=dsv \ --delimiterForDSV=$'\t' \ --enclosedBy '"' \ --escapeBy '\\' \ --showHeader=false \ -e "SELECT a.abc, a.mno, CASE WHEN a.xyz LIKE '%=%' THEN DECRYPT(STRING(b.decryptid), STRING(xyz)) ELSE a.xyz END as xyz FROM db.a a LEFT JOIN b ON (a.abc = b.def)" > "/tmp/abc.csv"
- 说明:
--outputformat=dsv支持自定义分隔符、包裹符、转义符,--enclosedBy '"'表示所有字段用双引号包裹,字段内部的双引号会自动用\转义,就算字段内有制表符也不会被识别为列分隔符。另外注意你原SQL里END as xyz,后面多了一个多余的逗号,会导致SQL执行报错,已经在上面的命令里删除。
问题3:校验每行字段数量是否符合要求
可以用awk命令一键校验,同时支持输出异常明细、返回校验状态码供自动化流程判断:
# 21列TSV校验命令,返回码0为全部正常,非0为存在异常行 awk -F'\t' ' BEGIN { expected_col = 21 err_count = 0 } NF != expected_col { err_count++ print "异常行号:"NR, "实际列数:"NF, "行内容:"$0 > "tsv_err.log" } END { print "校验完成,共"NR"行,异常行数:"err_count exit err_count } ' /tmp/abc.csv
执行后异常行会全部写入tsv_err.log文件,你可以根据命令返回码判断是否校验通过,接入CI/CD或者调度流程都可以直接使用。
内容的提问来源于stack exchange,提问作者SweetyP
相关产品推荐
相关产品推荐

