apachehive:如何使用unicode字符(八进制大于177)作为字段delim

8ulbf1ek  于 2021-06-02  发布在  Hadoop
关注(0)|答案(3)|浏览(396)

在我们的用例中,我们得到的utf-8文本数据的格式如下:

Data1§Data2
Data3§Data4

现在我们希望在ApacheHive中将data1和data3放在一列中,将data2和data4放在一列中。听起来很简单。
但是,我们无法指定§ 字符(unicode u+00a7“段号”见此处)作为字段分隔符。
我们试过以下几种方法,但都没有达到可以接受的效果。
1) 使用方法终止的正规域

ROW FORMAT DELIMITED FIELDS TERMINATED BY '§'

返回(注意?附加到每个单元格,在其他客户端中,unicode符号表示无法识别的符号)

+--------------------+--------------------+--+
| test.column1       | test.column2          |
+--------------------+--------------------+--+
| Data1?             | Data2?                |
| Data3?             | Data4?                |
+--------------------+--------------------+-

或八进制表示法

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\247'

ROW FORMAT DELIMITED FIELDS TERMINATED BY '\304\247'

返回:

+--------------------+--------------------+--+
| test.column1       | test.column2          |
+--------------------+--------------------+--+
| Data1?Data2        | NULL                  |
| Data3?Data4        | NULL                  |
+--------------------+--------------------+--+

2) 使用regexserde

ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "^([^\\]]+)\\\247([^\\]]+)$")

(在某些测试源数据中,将字段分隔符更改为/并使用\057(八进制表示/)可以得到正确的结果,但更改源数据对我们来说是不可行的。)

ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "^([^\\]]+)\\$([^\\]]+)$")

(在DESCRIPE格式的table语句中,这将产生:

input.regex  ^([^\\]]+)\\\uFFFD\uFFFD([^\\]]+)$

其中\ufffd是不可识别符号的unicode表示形式)
选择的结果总是相同的:

+--------------------+--------------------+--+
| test.column1       | test.column2          |
+--------------------+--------------------+--+
| NULL               | NULL                  |
| NULL               | NULL                  |
+--------------------+--------------------+--+

我目前的研究表明:
1) 配置单元不能使用八进制数高于177的不可打印ascii字符。在github上的一些其他代码中,指向这一点的指针让我感到惊讶,它说:
配置单元可以指定格式为“\ooo”的分隔符字符,其中ooo是介于000和177之间的三位八进制数。
2) 我还发现,在bigsql的文档(但在官方文档中没有)中,只有一个字节的字符可以用作字段delim,其中说明:
分隔符必须是单字节字符
至于我的研究§ (unicode u+00a7)是一个2字节字符(11000010:10100111)
这是不是意味着我不能使用这个分隔符,或者有其他方法可以使用它?
小更新,如果此问题未解决且有人需要它:
我尝试了以下方法:将数据暂存为一列表,然后进行转换§ 到,(逗号),然后用逗号分开。这适用于小样本数据,但对于包含200多个列的较大生产表则失败,并出现错误。

select
split(a.textcolumn, '\\,')[0] as column1
,split(a.textcolumn, '\\,')[1] as column2
from
(select translate(textcolumn, '§', ',') as textcolumn from database.stage) a;

错误如下:
sql错误:java.io.ioexception:org.apache.hadoop.hive.ql.metadata.hiveexception:计算translate时出错(staginstring,'§', ';') java.io.ioexception:org.apache.hadoop.hive.ql.metadata.hiveexception:计算translate时出错(staginstring,'§', ';') java.io.ioexception:org.apache.hadoop.hive.ql.metadata.hiveexception:计算translate时出错(staginstring,'§', ';') org.apache.hadoop.hive.ql.metadata.hiveexception:计算translate时出错(staginString,'§', ';') org.apache.hadoop.hive.ql.metadata.hiveexception:error evaluating 翻译(staginstring,'§', ';') java.lang.illegalargumentexception:空
更新2:
上面的方法是可行的,但是如果源数据不干净(有其他utf-8问题),它将抛出上面的错误。

hlswsv35

hlswsv351#

答案在我对上述问题的更新中。但是,如果数据不干净或包含我发现的其他有问题的字符,这将引发错误。

blpfk2vs

blpfk2vs2#

您需要使用创建表 Fields Terminated by '-89' “剖面符号”的十进制代码是167。

167 - 256 = -89

这个-89应该是您的分隔符。配置单元允许范围为-127到127的分隔符。
进一步阅读cloudera的以下片段。
https://www.cloudera.com/documentation/enterprise/5-8-x/topics/impala_create_table.html
注意:CREATETABLE子句字段终止于、转义于和行终止于具有用于其参数的字符串文字的特殊规则,因为它们都需要单个字符。可以使用由单引号或双引号包围的常规字符、八进制序列(如“\054”(表示逗号)或范围为“-127”…“128”(带引号但不带反斜杠)的整数,这些字符被解释为单字节ascii字符。从256中减去负值;例如,以“-2”结尾的字段将字段分隔符设置为ascii代码254,“冰岛刺”字符用作某些数据格式的分隔符。

brgchamk

brgchamk3#

我知道这是一个冷的情况,但这个问题可能会解决使用多个服务器。
实际上,配置单元默认serde(称为lazysimpleserde)只支持单字节分隔符。正如alpcoder所说,这是没有记录的。你需要阅读源代码来理解它。
MultiDelimiterSerde旨在支持多字符分隔符。幸运的是,它支持任何多字节字符。

相关问题