这个字符是什么?'*'?


48

一个朋友将一个命令粘贴到一个包含角色的Slack聊天室中*。这看起来很正常,*但不是:

$ uniprops '*​'
uniprops: no character named ‹*​›

如果uniprops在星号上运行时在计算机上键入时会得到:

$ uniprops '*'
U+002A ‹*› \N{ASTERISK}
    \pP \p{Po}
    All Any ASCII Assigned Basic_Latin Punct Is_Punctuation Common Zyyy Po P
       Gr_Base Grapheme_Base Graph X_POSIX_Graph GrBase Other_Punctuation
       Pat_Syn Pattern_Syntax PatSyn POSIX_Graph POSIX_Print POSIX_Punct Print
       X_POSIX_Print Punctuation Unicode X_POSIX_Punct

通过传递它,我还可以看到它不是实际的星号od

$ printf '*​' | od -c
0000000   * 342 200 213
0000004

正常人会给出:

$ printf '*' | od -c
0000000   *
0000001

这是一个更大的神秘人物:

*

和正常的星号(是的,它们看起来确实相同):

*

因此,uniprops不知道这是什么,我也无法在http://www.fileformat.info/上找到它。我确实知道粘贴它的朋友在OS X上(我在Linux上),并且它在他们的系统上作为常规星号起作用。我假设Slack以某种方式改变了它。那么,有人知道这个角色是什么吗?

请注意,您不能直接从问题中复制奇怪的字符。显然,Stack Exchange引擎剥离了尾随的非打印字符。单击“编辑”链接,然后从那里复制。


unipropsUnicode::TusslePerl模块中包含的一个简洁的小脚本,用于识别并打印有关您给它的字符的信息。


无法复制。我使用ord("*")了您粘贴的字符串和本机*密钥,并且两者都使用了相同的数字(42)。
日3

7
@MarchHo该死,SE引擎似乎正在吃掉它。我在发布之前进行了测试,可以复制奇怪的字符(尽管我开始理解问题是在那里添加了额外的非打印字符),但是我也不能从发布的问题中复制。您需要单击编辑链接并从那里复制。
terdon

2
奇怪的是,在Android应用上,带有空格的零会显示为正常空格。
derobert

1
有趣的是,当我从“ edit”粘贴到终端时urxvt,它已经显示为*<200b>
博多

如果您从代码部分(例如uniprops行)复制它,那么它将复制OK,而无需转到问题源。(也将其粘贴到Python3解释器显示中'*\u200b'
TessellatingHeckler,

Answers:


71

粘贴失败的原因不是因为星号(这是一个完美的常规星号),而是因为Unicode字符U + 200B。由于该字符是a ZERO WIDTH SPACE,因此复制时不会显示。

使用Python代码:

stro=u"'*​'?"
def uniconv(text):
    return " ".join(hex(ord(char)) for char in text)
uniconv(stro)

该函数uniconv将输入字符串(在这种情况下为u"'*'?")转换为十六进制格式的Unicode代码页等效项。u字符串的前缀将字符串标识为Unicode字符串。

我能够获得输出:

0x27 0x2a 0x200b 0x27 0x3f

我们可以清楚地看到0x270x2a并且0x3f是ASCII / Unicode十六进制的字符值'*?分别。剩下0x200b,因此可以识别字符。

请注意,当将Python代码粘贴到正文中时,SE的Markdown软件已删除了U + 200B字符。为了获得预期的结果,您需要使用“编辑”视图直接从标题复制它。


5
替换strhex将以十六进制输出代码点,从而使其更易于识别或查找。
deltab '16

也有称为专用Python模块unicodedata,通过它可以查询字符的名称,类别等
博德

4
ZERO WIDTH SPACE和ZERO WIDTH JOINER字符易于与试图阻止常见垃圾邮件术语的注释系统一起使用。例如,要指出,伯尼·桑德斯当选为参议院议员是社会主义者(没有绊倒“ Cialis”的垃圾邮件陷阱),如果尊重HTML实体,则将其写为“ Soci&zwj; alist”,或在“字符地图”中粘贴字符或等效(如果不是)。
蒙迪·哈德

27

在Ask Ubuntu聊天室中的@Rinzwind的帮助下,我发现问题根本不是字符。注意输出od

$ printf '*​' | od -c
0000000   * 342 200 213
0000004

342 200 213是另一种性质的八进制表示,我们可以利用这个网站来关注一下吧:

Character                   ​               
Character name                              ZERO WIDTH SPACE
Hex code point                              200B
Decimal code point                          8203
Hex UTF-8 bytes                             E2 80 8B
Octal UTF-8 bytes                           342 200 213
UTF-8 bytes as Latin-1 characters bytes     â <80> <8B>

因此,我实际上只有两个unicode字符,即正常*宽度和零宽度空格。


6
另一种方法是printf '\342\200\213' | uniname。(uniname来自uniutils软件包。)
deltab 2016年

1
该站点,您可以进行不同的格式转换:对于十六进制,它002A 200B为utf-8,2A E2 80 8B对于utf-16 ,对于002A 200B...
Hastur
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.