Wie konvertiere ich ein mit einem U + xxxxx-Code angegebenes Emoticon nach utf-8?

16

Emoticons scheinen mit einem Format von U + xxxxx angegeben zu werden,
wobei jedes x eine hexadezimale Ziffer ist.

Zum Beispiel ist U + 1F615 der offizielle Unicode-Konsortialcode fĂŒr das "verwirrte Gesicht" 😕

Da ich oft verwirrt bin, habe ich eine starke AffinitÀt zu diesem Symbol.

Die U + 1F615- Darstellung ist fĂŒr mich verwirrend, da ich dachte, dass die einzigen möglichen Codierungen fĂŒr Unicode-Zeichen 8, 16, 24 oder 32 Bit erfordern, wohingegen 5 Hexadezimalziffern 5 x 4 = 20 Bit erfordern.

Ich habe festgestellt, dass dieses Symbol in der Bash durch eine völlig andere Hex-Zeichenfolge dargestellt zu werden scheint:

$echo -n 😕 | hexdump
0000000 f0 9f 98 95                                    
0000004

$echo -e "\xf0\x9f\x98\x95"
😕

$PS1=$'\xf0\x9f\x98\x95  >'
😕  >

Ich hÀtte erwartet, dass U + 1F615 in etwas wie \ x00 \ x01 \ xF6 \ x15 konvertiert .

Ich sehe die Beziehung zwischen diesen beiden Kodierungen nicht?

Wenn ich ein Symbol in der Liste des offiziellen Unicode-Konsortiums suche , möchte ich diesen Code direkt verwenden können, ohne ihn mĂŒhsam manuell konvertieren zu mĂŒssen. dh

  • Finden des Symbols auf einer Webseite
  • Kopieren in die Zwischenablage des Webbrowsers
  • EinfĂŒgen in Bash, um den REAL-Code durch einen Hexdump zu finden.

Kann ich diesen 20-Bit-Code verwenden, um den 32-Bit-Code zu bestimmen?

Besteht eine Beziehung zwischen diesen beiden Zahlen?

Alex Ryan
quelle

Antworten:

20

UTF-8ist eine Codierung mit variabler LĂ€nge fĂŒr Unicode. Es ist so konzipiert, dass es eine Obermenge von ASCII ist. Einzelheiten zur Kodierung finden Sie in Wikipedia . \x00 \x01 \xF6 \x15wĂ€re UCS-4BEoder UTF-32BEKodierung.

Wenn Sie vom Unicode-Codepunkt zur UTF-8-Codierung gelangen möchten, gehen Sie davon aus, dass das Charmap des Gebietsschemas UTF-8 ist (siehe die Ausgabe von locale charmap).

$ printf '\U1F615\n'
😕
$ echo -e '\U1F615'
😕
$ confused_face=$'\U1F615'

Letzteres wird in der nÀchsten Version des POSIX-Standards enthalten sein .

AFAIK, dass Syntax wurde im Jahr 2000 durch das Stand-alone - GNU eingefĂŒhrt printfDienstprogramm (im Gegensatz zu dem printfNutzen des GNU - Shell), geholt echo/ printf/ $'...'builtins ersten von zsh2003 , ksh93 2004 bash im Jahr 2010 (wenn auch nicht richtig dort arbeitet bis 2014 ), wurde aber offensichtlich von anderen Sprachen inspiriert.

ksh93unterstĂŒtzt es auch als printf '\x1f615\n'und printf '\u{1f615}\n'.

$'\uXXXX'und $'\UXXXXXXXX'werden unterstĂŒtzt von zsh, bash, ksh93, mkshund FreeBSD sh, GNU printf, GNU echo.

Einige erfordern alle Ziffern (im \U0001F615Gegensatz zu \U1F615), obwohl dies in zukĂŒnftigen Versionen wahrscheinlich geĂ€ndert wird, da POSIX weniger Ziffern zulĂ€sst. In jedem Fall mĂŒssen Sie alle Ziffern , wenn die \UXXXXXXXXdurch hexadezimale Ziffern wie in gefolgt werden soll \U0001F615FOX, wie es \U1F615FOXgewesen wĂ€re $'\U001F615F'OX.

Einige werden zu dem Zeitpunkt, zu dem die Zeichenfolge analysiert wird, oder zu dem Zeitpunkt, zu dem sie erweitert wird, auf die Zeichen in der Codierung des aktuellen Gebietsschemas erweitert, andere nur in UTF-8, unabhĂ€ngig vom Gebietsschema. Wenn das Zeichen in der Codierung des aktuellen Gebietsschemas nicht verfĂŒgbar ist, variiert das Verhalten zwischen den Shells.

Um eine optimale PortabilitÀt zu erzielen, verwenden Sie es am besten nur in UTF-8-Gebietsschemas und verwenden Sie alle Ziffern und verwenden Sie es in $'...':

printf '%s\n' $'\U0001F615'

Beachten Sie, dass:

LC_ALL=C.UTF-8; printf '%s\n' $'\U0001F615'

oder:

{
  LC_ALL=C.UTF-8
  printf '%s\n' $'\U0001F615'
}

Wird nicht mit allen Schalen (einschließlich arbeiten bash) , weil das $'\U0001F615'wird analysiert , bevor LC_ALLzugeordnet ist. (Beachten Sie auch, dass es keine Garantie dafĂŒr gibt, dass ein System ein genanntes Gebietsschema hat. C.UTF-8)

Sie brauchen:

LC_ALL=C.UTF-8; eval "confused_face=$'\U0001F615'"

Oder:

LC_ALL=C.UTF-8
printf '%s\n' $'\U0001F615'

(Nicht innerhalb eines zusammengesetzten Befehls oder einer zusammengesetzten Funktion).


Um von der UTF-8-Codierung zum Unicode-Codepunkt zu gelangen, lesen Sie diese oder jene andere Frage .

$ unicode 😕 
U+1F615 CONFUSED FACE
UTF-8: f0 9f 98 95  UTF-16BE: d83dde15  Decimal: 😕
😕
Category: So (Symbol, Other)
Bidi: ON (Other Neutrals)

$ perl -CA -le 'printf "%x\n", ord shift' 😕
1f615
Stéphane Chazelas
quelle
2
Beachten Sie, dass, wenn \U1F615eine andere gĂŒltige Hexadezimalzahl folgt, angenommen wird, dass diese Teil der Escape-Sequenz ist. Damit es funktioniert, unabhĂ€ngig davon, worauf es folgt, muss es genĂŒgend fĂŒhrende Nullen haben, um genau acht Stellen lang zu sein:\U0001F615
Kasperd
@kasperd, danke. Ja, es ist erwÀhnenswert. Ich habe das in die Antwort aufgenommen.
Stéphane Chazelas
7

Hier ist eine Möglichkeit, von UTF-32 (Big Endian) nach UTF-8 zu konvertieren

$ confused=$(echo -ne "\x0\x01\xF6\x15" | iconv -f UTF-32BE -t UTF-8)     
$ echo $confused 
😕

Sie werden dort Ihren Hex-Wert bemerken 0x01F615, der mit einer zusĂ€tzlichen fĂŒhrenden 0 aufgefĂŒllt ist, um 32 Bits zu fĂŒllen.

Die Wikipedia-Seite zu UTF-8 erklÀrt die Umwandlung von einem Unicode-Codepunkt in seine UTF-8-Darstellung sehr deutlich. Es ist jedoch möglicherweise nicht die beste Idee, es in Shell-Skripten selbst zu tun.

UTF-32 hat eine feste Breite und die Entsprechung zwischen Codepoint und UTF-32-Darstellung ist trivial - der Wert ist der gleiche.

Matte
quelle
6

Schöne Art und Weise, es in deinem Kopf oder auf Papier zu tun:

  1. Stellen Sie fest, wie viele Bytes es sein werden: Werte unter U + 0080 sind ein Byte, andere unter U + 0800 sind 2 Bytes, andere unter U + 10000 sind 3 Bytes, andere 4 Bytes. In Ihrem Fall 4 Bytes.

  2. Konvertieren hex zu Oktal: 0373025.

  3. Ab Ende, abschÀlen 2 Oktalziffern zu einer Zeit , eine Folge von Oktalwerte zu erhalten: 037 030 025.

  4. Wenn Sie weniger Oktalwerte als die erwartete Anzahl von Bytes haben, eine zusĂ€tzliche 0 am Anfang hinzufĂŒgen: 000 037 030 025.

  5. FĂŒr alle , aber die erste, fĂŒgen Sie auf 0200bekommen: 000 0237 0230 0225.

  6. Zum ersten, hinzufĂŒgen , 0300wenn die erwarteten LĂ€nge 2 ist, 0340wenn es 3 ist, oder 0360wenn es 4 ist, zu erhalten: 360 0237 0230 0225.

Schreiben Sie jetzt als eine Reihe von Oktal entkommt: \360\237\230\225. Wenn Sie möchten, können Sie auch zurĂŒck in Hex konvertieren.

R ..
quelle