Apa karakter ini: '*'?

48

Seorang teman menempelkan perintah ke ruang obrolan Slack yang berisi karakter *. Ini terlihat seperti normal *tetapi tidak:

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

Sementara jika saya menjalankan unipropstanda bintang yang saya dapatkan saat mengetik di komputer saya, saya mendapatkan:

$ 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

Saya juga dapat melihat bahwa itu bukan tanda bintang yang sebenarnya dengan melewati od:

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

Sedangkan yang normal memberi:

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

Inilah karakter misteri yang sedikit lebih besar:

*

Dan tanda bintang normal (ya, mereka memang terlihat identik):

*

Jadi, unipropstidak tahu apa ini, dan saya juga tidak bisa menemukannya di http://www.fileformat.info/ . Saya tahu bahwa teman yang menempelnya ada di OS X (saya di Linux) dan itu bekerja di sistem mereka sebagai tanda bintang biasa. Saya berasumsi bahwa Slack entah bagaimana mengubahnya. Jadi, adakah yang tahu karakter apa itu?

Perhatikan bahwa Anda tidak dapat menyalin karakter aneh langsung dari pertanyaan. Rupanya, mesin Stack Exchange menghapus karakter yang tidak dicetak. Klik tautan "edit" dan salin dari sana.


unipropsadalah skrip kecil rapi yang termasuk dalam Unicode::Tusslemodul Perl yang mengidentifikasi dan mencetak informasi tentang karakter yang Anda berikan.

terdon
sumber
Tidak dapat mereproduksi Saya menggunakan ord("*")untuk string yang disisipkan dan *kunci asli , dan mendapat nomor yang sama untuk keduanya (42).
Maret
7
@MarchHo sial, mesin SE sepertinya memakannya. Saya menguji sebelum memposting dan dapat menyalin karakter aneh (walaupun, saya mulai mengerti bahwa masalahnya adalah ada tambahan, karakter non-cetak ditambahkan di sana) tetapi saya tidak dapat menyalin dari pertanyaan yang diposting juga. Anda perlu mengklik tautan edit dan menyalinnya dari sana.
terdon
2
Anehnya, pada aplikasi Android, nol dengan ruang ditampilkan seolah-olah itu adalah ruang normal.
derobert
1
Menariknya, ketika saya tempel dari 'edit' ke terminal saya urxvt, sudah ditampilkan sebagai *<200b>.
Bodo
Jika Anda menyalinnya dari bagian kode Anda, misalnya baris uniprops, maka itu menyalin OK tanpa harus pergi ke sumber pertanyaan. (Menempelkannya ke dalam interpreter Python3 '*\u200b'juga)
TessellatingHeckler

Jawaban:

71

Tempel gagal bukan karena tanda bintang, yang merupakan tanda bintang biasa, tetapi karena karakter Unicode U + 200B . Karena karakternya adalah ZERO WIDTH SPACE, ia tidak ditampilkan ketika disalin.

Menggunakan kode Python:

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

Fungsi uniconvmengubah string input (dalam hal ini, u"'*'?") ke dalam bentuk kode setara Unicode dalam format heksadesimal. The uawalan untuk string mengidentifikasi string sebagai string Unicode.

Saya bisa mendapatkan output:

0x27 0x2a 0x200b 0x27 0x3f

Kita dapat dengan jelas melihat itu 0x27, 0x2adan 0x3fmerupakan nilai heksadesimal ASCII / Unicode untuk karakter ', *dan ?masing - masing. Yang meninggalkan 0x200b, oleh karena itu mengidentifikasi karakter.

Perhatikan bahwa kode Python, ketika disisipkan ke dalam tubuh, memiliki karakter U + 200B dihapus oleh perangkat lunak Markdown SE. Untuk mendapatkan hasil yang diharapkan, Anda harus menyalinnya langsung dari judul menggunakan tampilan Edit.

March Ho
sumber
5
Mengganti strdengan hexakan menampilkan codepoint dalam heksadesimal, membuatnya lebih mudah untuk dikenali atau dicari.
deltab
Ada juga modul python khusus yang disebut unicodedata, yang dengannya Anda dapat menanyakan nama karakter, kategori dll.
bodo
4
Karakter ZERO WIDTH SPACE dan ZERO WIDTH JOINER berguna untuk digunakan dengan sistem komentar yang mencoba memblokir istilah spam yang umum. Misalnya, untuk menunjukkan bahwa Bernie Sanders terpilih ke Senat sebagai Sosialis (tanpa tersandung perangkap spam untuk "Cialis") tuliskan sebagai "Soci & zwj; alist" jika Entitas HTML dihormati, atau tempelkan karakter dari Character Map atau setara jika tidak.
Monty Harder
27

Dengan bantuan @Rinzwind di ruang obrolan Tanya Ubuntu, saya menemukan bahwa masalahnya bukanlah karakter sama sekali. Perhatikan output dari od:

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

Ini 342 200 213adalah representasi oktal dari karakter lain dan kita dapat menggunakan situs ini untuk mencarinya:

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>

Jadi, yang sebenarnya saya miliki adalah dua karakter unicode, ruang normal *dan nol lebar.

terdon
sumber
6
Cara lain untuk melakukannya adalah printf '\342\200\213' | uniname. (Uniname berasal dari paket uniutils.)
deltab
1
Dari situs ini Anda dapat memiliki konversi format yang berbeda: untuk HEX itu memberikan 002A 200B, untuk utf-8 2A E2 80 8Buntuk utf-16 002A 200B...
Hastur