关于 "..." 与 "…"

UX: 这次我们把按钮的文字改一下,从 “Continue” 改成 “Save…”.

我:OK。简单,三个点而已。

Reviewer: 不,那可不只是三个点

我:三个点还能有不一样!?

Reviewer:对,我们应该用 “…” 而不是 “…”。

我:嗯?听说一席话,如听一席话。

Reviewer:不,你仔细看看。"…" 是一个字符,而 "..." 是三个。

我:这是什么奇怪的编码吗?

Reviewer:但也说不上奇怪,前者是 “U+2026”,而后者是三个 “U+002E”。

我(查了查 unicode-table.com):还真是。但有必要计较这个问题吗,难道我们要为了省两个字符?我们搞前端的,不缺那么点内存吧

Reviewer:对,但说起来简单。这涉及到排版。

我:哦?

Reviewer:如我前面所说,三个点都在一个字符内,所以这三个点是不会断开的。但如果用三个标点的话,那么就可能因为屏幕空间的变化,为了适配网页尺寸,会出现第一个点在第一行,第二第三个点在第二行的情况。

我:哦,原来是这样,是为了美观呀!

Reviewer:对。实际应用中,可不止这个,还有 “I don’t know” 中的单引号。如果你直接在编辑器中,比如 vscode 中,你会看到 ' 长得很类似。同样是用键盘回车键左边的按键敲出来的,但实际会因为编辑器的不同而有不同效果,有些会是 ' (U+0027),而有些则是 (U+2032)。

我:还真是。那我怎么知道该用哪个?

Reviewer:一般会有一个 UXW(UX writer)对这方面比较熟悉,可以问他们。但话说回来,有些工程师看着这个字符串简单,就没有用复制,而是直接手敲了,比如刚刚讲到的三个点。这反而导致了实际的 UI 效果是有隐患的。另外,https://material.io/archive/guidelines/style/writing.html#writing-capitalization-punctuation 恰好讲了一些标点的例子,你可以去看看。

我:好!那我们有没有 linter 之类的可以使用。

Reviewer:你可以在我们项目里加一个 presubmit script。这样,它能在提交代码时警告工程师。要不你去实现检测 ... 吧。

我:好!

聊完后,我开始写起这个脚本。项目里用的是 python,那么用 python 的话,正则表达式就是 \u002e\u002e\u002e,也就是这个样子了:

1
2
3
4
import re

p = re.compile('\u002e\u002e\u002e')
print(p.search("downloading...").group())

看一下输出,是这个样子:dow

嗯?怎么回事,为什么不是 ...。难道我哪里打错了?但仔细看了不下十遍,也没发现啥疑点。把字符换成 Saving... 试试,但也没有正确匹配。

用其他语言试试:

1
2
> "downloading...".match(/\u002e\u002e\u002e/)
[ '...', index: 11, input: 'downloading...', groups: undefined ]

为什么用 js 就可以?

折腾了半个多小时,无奈去问了问擅长 Python 的同事。

同事:你用 p = re.compile('[\u002e]{3}') 试试?

我试了试,发现还真可以!真是怪了,这两者不是应该没区别的吗!?

同事:不,有区别。我不知道 js 里是怎么处理的,但在 python 里,'\u002e\u002e\u002e' 就是 '...'。你相当于拿了三个通配符去匹配,当然不管怎么匹配,也只能匹配到字符串最开头的三个字母!

我:哎,原来是踩了一个坑!

LICENSED UNDER CC BY-NC-SA 4.0