背景
在处理数据时,当业务数据同步至MaxCompute后,会产生一些含异常字符的脏数据,比如字段中包含了一个不可见字符,在DataWorks中显示不出来,但在BI界面又会显示成其他字符,影响整体观感。这种情况,通常我们的解法是,将异常的字符洗掉,下面来介绍几种常见的处理异常字符的方法。
问题描述
定位
如下图,可以看到“异常name”和“正常name”的 length值 不同,多了个不可见字符,但是我们并不能看出来啥。后期做数据处理或数据展示可能成为一个难以定位的问题。
SELECT name as 异常name, LENGTH(name)as 异常name长度,'北京'as 正常name, LENGTH('北京')as 正常name长度 from tbl1 where name RLIKE '北京';
结果:
小技巧
- 我们可以通过在线Unicode编码转换工具,将数值粘贴过去,获取到对应的Unicode码。同理也可以获取其他异常字符的Unicode码,以便后续处理。
- 输入异常 vs 正常的字符串,对比 Unicode 差异可以倒推不可见字符为“ \u200b”。
解决方案
- 定位到问题后,回顾数据清洗的常规方案,想办法把消掉这种不可见字符
方案 |
描述 |
备注 |
本case是否适用 |
trim()函数 |
常规的首尾不可见字符处理 |
适用首尾部的空格、tab、换行 |
Yes |
replace()函数 |
定向剔除字符串 |
适用于单个待替换的字符,多个需要层层嵌套 |
Yes |
正则替换函数 |
定向剔除一类字符串 |
通过正则匹配符,替换一类字符串 |
Yes |
方案1:trim() - 替换
- MaxCompute的trim()函数支持通过设置参数的方式调特色字符
- TRIM相关文档:https://help.aliyun.com/document_detail/455667.html
效果如下:
- 利用 trim() 函数将数值中的异常不可见字符替换为正常空值字符(不可见字符可通过在线Unicode编码转换工具Unicode转中文复制一下)
SELECT name as 异常name, LENGTH(name)as 异常name长度, trim(name,'')as 正常name, LENGTH(trim(name,''))as 正常name长度 from tbl1 where name RLIKE '北京';
结果:
方案2:replace() - 替换
- 优点:点对点思路解决问题,方便快捷
- 缺点:适用待替换的字符只有一个情况,如果有多个,需要再套一层replace函数,不容易维护
- REPLACE相关文档:https://help.aliyun.com/document_detail/455611.html
效果如下:
- 利用 replace() 函数将数值中的异常不可见字符替换为正常空值字符(不可见字符可通过在线Unicode编码转换工具Unicode转中文复制一下)
SELECT name as 异常name, LENGTH(name)as 异常name长度, replace(name,'','')as 正常name, LENGTH(replace(name,'',''))as 正常name长度 from tbl1 where name RLIKE '北京';
结果:
方案4:正则表达式 - 替换
- 使用函数一层一层替换会比较麻烦,目前MaxCompute支持通过正则表达式匹配出异常的字符
- 只要筛选出了带有异常的一部分字符,再处理就方便很多了
- 例如上文中的不可见字符,Unicode码为“\u200b”,通过执行如下SQL
select id,name from tbl1 where name rlike '[\\x{200b}]';
结果返回:
- 此时如果再用regexp_replace()函数可以替换掉这一部分含不可见字符的数值
-- regexp_replace()函数SELECT name as 异常name, LENGTH(name)as 异常name长度, regexp_replace(name,'[\\x{200b}]','',0)as 正常name, LENGTH(regexp_replace(name,'[\\x{200b}]','',0))as 正常name长度 FROM tbl1;
结果:
总结
针对于SQL中的不可见字符或者其他中文等异常字符,都可以使用方案3中的筛选方式筛出来,然后再做后续的替换或其他操作就可以了。