快捷搜索:  汽车  科技

无法显示的特殊空白字符(扒一扒史上最坑的空白字符)

无法显示的特殊空白字符(扒一扒史上最坑的空白字符)遇到这个问题的场景是:我方使用联系方式请求第三方接口,报联系方式格式错误,第一反应就是对方接口出问题了,截图和使用文本文档复制报文给对方(见下图),对方也认为是自身问题,因为报文看起来有问题,对方表示他们打出的日志也是这样,不存在编码格式不统一问题,直到对方说他手打报文发送就没问题,我才意识到,是不是有什么奇奇怪怪的字符在捉妖,毕竟以前遇到过带空格,带tab的情况。 这是标点范围内的,又是不可见的标点,一般人很难察觉。 不使用复杂的的正则校验,就校验数字11位,测试复制和手动输入的结果: public static void main(String[] args) { System.out.println(ReUtil.isMatch ("(1){1}[0-9]{10}" "\u202D1

作为一名程序员,无论是前端开发还是后端开发,都可能和正则表达式打交道,有时候明明肉眼可见是符合正则的,为何总是过不去呢?下面先贴一个例子,最近遇到的坑,有兴趣可以先试一下复制到记事本和IDE工具内看下。

无法显示的特殊空白字符(扒一扒史上最坑的空白字符)(1)

程序员在线找BUG

如下是一个手机号,我们需要通过正则校验手机号合法性,看起来是完全符合手机号规则的

‭13666668888‬

不使用复杂的的正则校验,就校验数字11位,测试复制和手动输入的结果:

public static void main(String[] args) { System.out.println(ReUtil.isMatch ("(1){1}[0-9]{10}" "\u202D13666668888\u202C")); System.out.println(ReUtil.isMatch ("(1){1}[0-9]{10}" "13666668888")); }

这是什么奇奇怪怪的东西,为什么复制到IDE工具内就多了些奇奇怪怪的,\u202D和\u202C显然是Unicode编码,具体不在做多解释,查阅Unicode编码范围可知:

2000-206F:常用标点(General Punctuation)

这是标点范围内的,又是不可见的标点,一般人很难察觉。

遇到这个问题的场景是:我方使用联系方式请求第三方接口,报联系方式格式错误,第一反应就是对方接口出问题了,截图和使用文本文档复制报文给对方(见下图),对方也认为是自身问题,因为报文看起来有问题,对方表示他们打出的日志也是这样,不存在编码格式不统一问题,直到对方说他手打报文发送就没问题,我才意识到,是不是有什么奇奇怪怪的字符在捉妖,毕竟以前遇到过带空格,带tab的情况。

无法显示的特殊空白字符(扒一扒史上最坑的空白字符)(2)

问题报文

二话不说 报文复制到IDE看一眼,当初查换行和tab就是这样做的。

代码正如之前所发的,有两个Unicode编码,再次和录入联系方式的人员确认:

无法显示的特殊空白字符(扒一扒史上最坑的空白字符)(3)

似乎马上要破案了,联系方式是对方微信发的,可能是从哪里复制过来的,那么,一般联系会从通讯录或者其他地方复制,网上一搜,果然水果机是有这种机制的,那么为何要引入这些Unicode编码呢?查到有如下说法

在所有主要的Web浏览器中内存中的字符顺序(逻辑)与它们显示的顺序(可视)是不同的。Unicode 定义了它其中每个字符的方向属性,浏览器应用的一组规则(通过这个来进行自动判断文本Unicode方向属性应该使用哪种方向)在显示时产生正确的顺序由Unicode双向算法进行描述,也可简称为BIDI算法。控制字符,有时候也称非打印字符,是出现在特定的信息文本中,表示某一控制功能的字符。这类字符并不显示,只包含某种特定的功能。

说人话,就是有些场景,数据库之类的存储的是左到右,但是显示不行,据说阿拉伯文相关的环境是右到左的,中文英文是左到右,那么要做到国际化就要对对应文本进行处理。

日常我们书写文字会知道,书写的方向是决定于所书写的文字,汉字、拉丁文字是从左至右,阿拉伯文、希伯来文则是从右至左。相应的,Unicode 字符在设计时就考虑了不同文字方向性的问题,因此定义了每个 Unicode 字符的方向属性。

只定义每个Unicode字符方向还是不足够的,很多时候需要将整体字符串左右反转,那么控制字符就派上用场了。

U 202A: LEFT-TO-RIGHT EMBEDDING (LRE)

U 202B: RIGHT-TO-LEFT EMBEDDING (RLE)

U 202D: LEFT-TO-RIGHT OVERRIDE (LRO)

U 202E: RIGHT-TO-LEFT OVERRIDE (RLO)

U 202C: POP DIRECTIONAL FORMATTING (PDF)

PDF即是终点,水果机使用LRO和PDF即达到了控制效果,我们可以测试下LRO相反的RLO的作用,从override的意思来看,就是覆盖了原有排版,上代码测试:

public static void main(String[] args) { System.out.println("13666668888"); System.out.println("\u202D13666668888\u202C"); System.out.println("\u202E13666668888\u202C"); }

13666668888

‭13666668888‬

‮13666668888‬

有兴趣的可以复制最后一个到IDE或者文本编辑工具看下效果。

水果机通过控制字符控制了字符的左右方向和排版方向,但是这可苦了我们这些程序员了,一不小心就找不到问题所在了,所以对于此类问题,最好就是前端或者后端做正则校验或者替换掉有问题的字符,指望系统操作人员去手打,既容易出错还不方便。相关示例代码如下:

public static void main(String[] args) { System.out.println("13666668888"); System.out.println("\u202D13666668888\u202C"); System.out.println("\u202E13666668888\u202C".replaceAll("\\p{Cf}" "")); }

13666668888

‭13666668888‬

13666668888

可以看到第三个顺序展示了,其中\p{Cf}是不显示的Uniicode的一个总称,经测试邮箱内的特殊字符、区号或者分机号和电话相连的-是不会被替换的,不过查阅了下有\p{P}的说明,也有参数为C的说明,但是没Cf的说明,不知道哪位大神可以补充说明下。

以上就是史上最坑空白字符的发现过程和具体用途,有兴趣的可以就里面具体的点再查阅下相关文档,此处不再叙述。

猜您喜欢: