Co to za znak: „*”?

48

Przyjaciel wkleił polecenie do pokoju rozmów Slack, który zawierał postać *. To wygląda normalnie, *ale nie jest:

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

Chociaż jeśli uruchomię unipropsgwiazdkę, którą otrzymuję podczas pisania na moim komputerze, otrzymuję:

$ 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

Widzę też, że nie jest to prawdziwa gwiazdka, przepuszczając ją od:

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

Podczas gdy normalny daje:

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

Oto tajemnicza postać nieco większa:

*

I normalna gwiazdka (tak, wyglądają identycznie):

*

Więc unipropsnie wie, co to jest i nie mogę tego znaleźć na stronie http://www.fileformat.info/ . Wiem, że przyjaciel, który go wkleił, jest w systemie OS X (jestem w systemie Linux) i że działa on w ich systemie jako zwykła gwiazdka. Zakładam, że Slack jakoś to zmienił. Czy ktoś ma pojęcie, czym jest ta postać?

Pamiętaj, że nie możesz skopiować dziwnej postaci bezpośrednio z pytania. Najwyraźniej silnik Stack Exchange usuwa końcowe znaki niedrukowalne. Kliknij link „edytuj” i skopiuj stamtąd.


unipropsjest zgrabnym, małym skryptem zawartym w Unicode::Tusslemodule Perla, który identyfikuje i drukuje informacje o nadanym znaku.

terdon
źródło
Nie można odtworzyć. Użyłem ord("*")twojego wklejonego ciągu i *klucza natywnego , i dostałem ten sam numer dla obu (42).
Marzec Ho
7
@Marcho cholera, silnik SE wydaje się go jeść. Testowałem przed opublikowaniem i mogłem skopiować dziwną postać (chociaż zaczynam rozumieć, że problem polega na tym, że dodano tam dodatkowe, niedrukowalne znaki), ale nie mogę również skopiować z zadanego pytania. Musisz kliknąć link edycji i stamtąd skopiować.
terdon
2
Co dziwne, w aplikacji na Androida zero ze spacją jest wyświetlane tak, jakby to była normalna spacja.
derobert
1
Co ciekawe, kiedy wklejam „edytuj” do mojego terminala urxvt, jest on już wyświetlany jako *<200b>.
Bodo
Jeśli skopiujesz go z sekcji kodu, np. Wiersza uniprops, skopiuje OK, bez potrzeby przechodzenia do źródła pytania. (Wklejanie go również do interpretera języka Python3 '*\u200b')
TessellatingHeckler

Odpowiedzi:

71

Wklejanie nie powiodło się nie z powodu gwiazdki, która jest idealnie regularną gwiazdką, ale z powodu znaku Unicode U + 200B . Ponieważ znak jest znakiem ZERO WIDTH SPACE, nie jest wyświetlany po skopiowaniu.

Za pomocą kodu Python:

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

Funkcja uniconvkonwertuje ciąg wejściowy (w tym przypadku u"'*'?") na ich ekwiwalenty strony kodowej Unicode w formacie szesnastkowym. uPrefiks ciąg identyfikujący ciąg jako ciąg znaków Unicode.

Byłem w stanie uzyskać wynik:

0x27 0x2a 0x200b 0x27 0x3f

Widzimy wyraźnie, że 0x27, 0x2ai 0x3fsą wartościami szesnastkowym ASCII / Unicode dla znaków ', *i ?odpowiednio. To pozostawia 0x200b, identyfikując w ten sposób charakter.

Zauważ, że kod Pythona po wklejeniu do ciała miał znak U + 200B usunięty przez oprogramowanie Markdown SE. Aby uzyskać oczekiwany wynik, musisz skopiować go bezpośrednio z tytułu za pomocą widoku Edycja.

March Ho
źródło
5
Wymiana strz hexwyjściem będzie codepoints w systemie szesnastkowym, co czyni je łatwiej rozpoznać czy patrzeć w górę.
deltab
Istnieje również dedykowany moduł python unicodedata, za pomocą którego można wyszukiwać nazwy postaci, kategorie itp.
Bod
4
Znaki ZERO WIDTH SPACE i ZERO WIDTH JOINER są przydatne w systemach komentarzy, które próbują blokować typowe warunki spamu. Na przykład, aby zaznaczyć, że Bernie Sanders został wybrany do Senatu jako socjalista (bez wyrzucania pułapki na spam dla „Cialis”), napisz go jako „Soci & zwj; alist”, jeśli przestrzegane są jednostki HTML, lub wklej postać z mapy znaków lub równoważny, jeśli nie są.
Monty Harder
27

Z pomocą @Rinzwind w czacie Ask Ubuntu doszedłem do wniosku, że problemem wcale nie jest postać. Zwróć uwagę na wynik od:

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

342 200 213Jest ósemkowa reprezentacja innego charakteru i możemy korzystać z tej strony , aby to sprawdzić:

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>

Więc tak naprawdę miałem dwa znaki Unicode, normalną *i zerową szerokość.

terdon
źródło
6
Innym sposobem na to jest printf '\342\200\213' | uniname. (uniname pochodzi z pakietu uniutils.)
deltab
1
Z tej strony możesz mieć różne konwersje formatów: dla HEX daje 002A 200B, dla utf-8 2A E2 80 8Bdla utf-16 002A 200B...
Hastur