Hive - 加载以管道开头的管道分隔数据

Hive - Load pipe delimited data starting with pipe

假设我想在 Hive 中创建一个包含 4 列的简单 table 并加载一些以管道开头的管道分隔数据。

CREATE table TEST_1 (
COL1  string,
COL2  string,
COL3  string,
COL4  string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '|';

原始数据:

|123|456|Dasani Bottled|5|,   
|124|455|Test Bottled |7|      

Table 获取类似

的日期
----------------------------------
COL1  COL2   COL3     COL4
----------------------------------
      123   456     Dasani Bottled
      123   455     Test Bottled
----------------------------------

COL1 清空,最后一列未加载。 我尝试使用 Hadoop put 命令加载 csv 文件。

帮我解决这个问题。

您可以通过两种方式解决这个问题。

  1. 在处理文件之前删除第一列。这是干净且更可取的解决方案。
cut -d "|" -f 2- input_filename > output_filename

然后使用此 output_filename 作为加载过程的输入。

-d "|" - 这表示,使用管道作为分隔符。 -f 2- - 这表示,提取第一个字段后的所有内容。

  1. 像这样在 table 的开头添加一个虚拟列
CREATE table TEST_1 (
dummy string,
COL1  string,
COL2  string,
COL3  string,
COL4  string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '|';

然后继续加载数据。 然后您可以忽略此虚拟列或将数据存储到没有此列的最终 table 或在此之上创建视图以排除此虚拟列。

如果无法修复数据文件,您可以使用 RegexSerDe 而不是 LasySimpleSerDe(文本文件的默认 SerDe)。

定义您的数据在正则表达式中的外观。每列在正则表达式中应该有相应的捕获组 ()。

要在创建 table 之前测试正则表达式的工作原理,请使用 regex_replace

select regexp_replace('|123|456|Dasani Bottled|5|, ', --your row example
                      '^\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|.*', --4 groups are in the regex
                     '   '); --output space delimited fields 

结果:

123 456 Dasani Bottled 5

如果正则表达式按预期工作,创建 table(不一定是外部的):

create external table TEST_1 (
COL1  string,
COL2  string,
COL3  string,
COL4  string
) 
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' 
WITH SERDEPROPERTIES ('input.regex'='^\|(.*?)\|(.*?)\|(.*?)\|(.*?)\|.*')
location ....
;

然后将文件复制到 table 位置或使用 LOAD 命令。