您的位置:首页 > 其它

HIVE针对反斜杠的正则替换问题

2013-02-28 15:31 183 查看
最近收到一份需求:

有两张表 one 和 two . 两张表都有一个字段name,现在要求从one 导入到two 中。

要求是

name字段有可能为空 ,在HIVE中默认是用"\N"来表示空,也就是ONE表在HDFS上文件包含"\N"。

同时表ONE的NAME字段中有可能包含"\r"的转行符。

ONE表类似的HDFS文件系统如下
ID NAME
1, \N
2, licl\r

现在要求导入到表TWO后,\N表示为字符串NULL,并且将\r替换成\n

导入后TWO表的HDFS文件系统应该如下

ID NAME

1, NULL

2, licl\n

原始语句:insert overwrite table TWO select id,name from ONE;

我们的思路很简单,首先处理NULL的情况,你可以使用serialization.null.format
属性来修改TWO的表结构属性。但是当时我受到环境制约不允许这样做。接下来用coalesce函数处理NAME,coalesce(A,B,C)代表返回第一个不是NULL的值

于是函数变为了insert overwrite table TWO select id,coalesce(name,'NULL') from ONE;

接下来是难点,由于HIVE是采用JAVA编写的 "\"在JAVA中有着特殊的意义,同时还涉及到了正则表达式,更加复杂了。

最初我的语句是这样的。

insert overwrite table TWO select id,regexp_replace(coalesce(name,'NULL'),‘\r’,'\n') from ONE;

发现根本不起作用。

通过查询源码,发现我的 '\r' 在经过regexp_replace函数的时候变成了对象 TEXT("\\r"),这是由于JAVA引起的。

我的正则(‘\r’)也不起作用,因为正则遇到\的时候需要使用两个\\代表一个\,同时由于这个操作是在JAVA中进行的。反斜杠的数量应该再乘以2.

所以语句改成了:

insert overwrite table TWO select id,regexp_replace(coalesce(name,'NULL'),‘\\\\r’,'\\n') from ONE;

发现TWO变成了

ID NAME

1, NULL

2, licln

n的前面少了一个反斜杠,于是语句变成了:
insert overwrite table TWO select id,regexp_replace(coalesce(name,'NULL'),‘\\\\r’,'\\\\n') from ONE;

这个程序在客户端运行的十分好。

TWO表变成了

ID NAME

1, NULL

2, licl\n

但是!当我采用JDBC的模式的时候,发现第二条记录完全没有变化,也就是说正则匹配又失败了。

我推测是jdbc传输语句的问题,反斜杠的数量再次发生了变化,于是索性。

insert overwrite table TWO select id,regexp_replace(coalesce(name,'NULL'),‘\\\\\\\\r’,'\\\\\\\\n') from ONE;

这次JDBC发送的语句也执行的很好。

至此,我们的语句写完了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: