Nhân vật này là gì: '*'?


48

Một người bạn đã dán lệnh vào một phòng chat Slack có chứa nhân vật *. Điều này trông giống như bình thường *nhưng không phải là:

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

Trong khi nếu tôi chạy unipropstrên dấu sao tôi nhận được khi gõ trên máy thì tôi nhận được:

$ 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

Tôi cũng có thể thấy rằng đó không phải là một dấu sao thực sự bằng cách chuyển qua od:

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

Trong khi người bình thường cho:

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

Đây là nhân vật bí ẩn lớn hơn một chút:

*

Và dấu hoa thị bình thường (vâng, chúng trông giống hệt nhau):

*

Vì vậy, unipropskhông biết đây là gì và tôi cũng không thể tìm thấy nó trên http://www.fileformat.info/ . Tôi biết rằng người bạn đã dán nó trên OS X (tôi đang dùng Linux) và nó hoạt động trên hệ thống của họ như một dấu hoa thị thông thường. Tôi giả định rằng Slack bằng cách nào đó đã thay đổi nó. Vậy, có ai có ý kiến ​​gì về nhân vật đó không?

Lưu ý rằng bạn không thể sao chép ký tự lạ trực tiếp từ câu hỏi. Rõ ràng, công cụ Stack Exchange loại bỏ các ký tự không in dấu. Thay vào đó, nhấp vào liên kết "chỉnh sửa" và sao chép từ đó.


unipropslà một tập lệnh nhỏ gọn trong Unicode::Tusslemô-đun Perl xác định và in thông tin về ký tự bạn cung cấp.


Không thể tái tạo. Tôi đã sử dụng ord("*")cho chuỗi đã dán của bạn và *khóa gốc và có cùng số cho cả hai (42).
Tháng 3 ngày

7
@MarchHo chết tiệt, động cơ SE dường như đang ăn nó. Tôi đã thử nghiệm trước khi đăng và có thể sao chép ký tự lạ (mặc dù, tôi bắt đầu hiểu rằng vấn đề là có thêm ký tự không in được thêm vào đó) nhưng tôi cũng không thể sao chép từ câu hỏi đã đăng. Bạn cần nhấp vào liên kết chỉnh sửa và sao chép từ đó.
terdon

2
Điều kỳ lạ là trên ứng dụng Android, số không có không gian được hiển thị như thể đó là một không gian bình thường.
derobert

1
Thật thú vị, khi tôi dán từ 'chỉnh sửa' vào thiết bị đầu cuối của mình urxvt, nó đã được hiển thị dưới dạng *<200b>.
Bodo

Nếu bạn sao chép nó từ phần mã của bạn, ví dụ như dòng uniprops, thì nó sao chép OK mà không cần phải đi đến nguồn câu hỏi. (Dán nó vào trình thông dịch Python3 cũng hiển thị '*\u200b')
TessellatingHeckler

Câu trả lời:


71

Việc dán thất bại không phải vì dấu hoa thị, đó là dấu hoa thị hoàn toàn thông thường, mà vì ký tự Unicode U + 200B . Vì ký tự là một ZERO WIDTH SPACE, nó không hiển thị khi được sao chép.

Sử dụng mã Python:

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

Hàm này uniconvchuyển đổi chuỗi đầu vào (trong trường hợp này u"'*'?") thành tương đương mã hóa Unicode của chúng ở định dạng thập lục phân. Các utiền tố vào chuỗi xác định các chuỗi như là một chuỗi Unicode.

Tôi đã có thể có được đầu ra:

0x27 0x2a 0x200b 0x27 0x3f

Chúng tôi có thể thấy rõ rằng 0x27, 0x2a0x3flà ASCII / Unicode giá trị thập lục phân cho các nhân vật ', *?tương ứng. Điều đó để lại 0x200b, do đó xác định các nhân vật.

Lưu ý rằng mã Python, khi được dán vào cơ thể, đã xóa ký tự U + 200B bằng phần mềm Markdown của SE. Để có được kết quả mong đợi, bạn cần sao chép nó trực tiếp từ tiêu đề bằng cách sử dụng chế độ xem Chỉnh sửa.


5
Thay thế strbằng hexsẽ xuất ra các điểm mã theo hệ thập lục phân, làm cho chúng dễ nhận biết hoặc tra cứu hơn.
deltab

Ngoài ra còn có một mô-đun python chuyên dụng được gọi unicodedata, trong đó bạn có thể truy vấn tên nhân vật, thể loại, v.v.
bodo

4
Các ký tự ZERO WIDTH SPACE và ZERO WIDTH THAM GIA rất tiện để sử dụng với các hệ thống nhận xét cố gắng chặn các thuật ngữ spam phổ biến. Chẳng hạn, để chỉ ra rằng Bernie Sanders đã được bầu vào Thượng viện với tư cách là Chủ nghĩa xã hội (không vấp bẫy thư rác cho "Cialis") viết nó thành "Soci & zwj; alist" nếu các Thực thể HTML được tôn trọng hoặc dán vào ký tự từ Bản đồ nhân vật hoặc tương đương nếu họ không.
Monty Harder

27

Với sự giúp đỡ của @Rinzwind trong phòng trò chuyện Ask Ubuntu, tôi phát hiện ra rằng vấn đề không phải là nhân vật. Lưu ý đầu ra của od:

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

Đây 342 200 213là một đại diện bát phân của một nhân vật khác và chúng ta có thể sử dụng trang web này để tìm kiếm nó:

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>

Vì vậy, những gì tôi thực sự có là hai ký tự unicode, không gian bình thường *và không gian rộng.


6
Một cách khác để làm điều đó là printf '\342\200\213' | uniname. (uniname là từ gói uniutils.)
deltab

1
Từ trang web này, bạn có thể có các chuyển đổi định dạng khác nhau: đối với HEX, nó cung cấp 002A 200B, cho utf-8 2A E2 80 8Bcho utf-16 002A 200B...
Hastur
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.