2012-01-09 6 views
33

Io uso curl di ottenere qualche risposta URL, è la risposta JSON e contiene caratteri nazionali unicode escape come \u0144 (ń) e \u00f3 (ó).Come convertire uXXXX unicode UTF-8 utilizzando gli strumenti della console in * nix

Come posso convertirli in UTF-8 o qualsiasi altra codifica da salvare nel file?

+1

Vedi anche Unix e Linux: ** [In bash, come posso convertire un Unicode Codepoint \ [0-9A-F \] nel personaggio printabale?] (Http: // unix .stackexchange.com/questions/12273) ** – hippietrail

risposta

26

Non so quale distribuzione si utilizza, ma uni2ascii deve essere incluso.

$ sudo apt-get install uni2ascii 

Esso dipende solo libc6, quindi è una soluzione leggera (uni2ascii i386 4,18-2 è 55,0 kB su Ubuntu)!

Poi, per usarlo:

$ echo 'Character 1: \u0144, Character 2: \u00f3' | ascii2uni -a U -q 
Character 1: ń, Character 2: ó 
28

potrebbe essere un po 'brutto, ma echo -e dovrebbe farlo:

echo -en "$(curl $URL)" 

-e interpreta fughe, -n sopprime il newline echo normalmente aggiungere.

Nota: l'escape \u funziona nella bash incorporata echo, ma non /usr/bin/echo.

Come indicato nei commenti, si tratta di bash 4.2+ e 4.2.x hanno un bug che gestisce valori 0x00ff/17 (0x80-0xff).

+0

Non penso che '\ u' sia una sequenza di escape supportata. – cmbuckley

+1

@cbuckley Funziona per me. – Kevin

+0

È questo zsh per caso? Nel qual caso, 's/supportato/generalmente supportato /' :-) – cmbuckley

18

Supponendo che il \u è sempre seguita da esattamente 4 cifre esadecimali:

#!/usr/bin/perl 

use strict; 
use warnings; 

binmode(STDOUT, ':utf8'); 

while (<>) { 
    s/\\u([0-9a-fA-F]{4})/chr(hex($1))/eg; 
    print; 
} 

Il binmode mette uscita standard in modalità UTF-8. Il comando s... sostituisce ogni occorrenza di \u seguita da 4 cifre esadecimali con il carattere corrispondente. Il suffisso e fa sì che la sostituzione venga valutata come un'espressione anziché trattata come una stringa; lo g dice di sostituire tutte le occorrenze piuttosto che solo la prima.

È possibile salvare quanto sopra in un file da qualche parte nel proprio $PATH (non dimenticare lo chmod +x). Filtra l'input standard (o uno o più file denominati sulla riga di comando) sull'output standard.

+0

soluzione semplice ed efficiente – rupps

+0

!! Passerò al modo opposto da [questo codice] (http://icompile.eladkarako.com/yet-another-javascript-unicode-encodedecode/) più avanti .. –

+0

Perché diavolo dovrei codificare qualcosa per trasformare da uno standard ad un altro? La ruota era già stata inventata ... –

8

Non fare affidamento sulle espressioni regolari: JSON presenta alcuni casi angolari con escape \u e punti di codice non BMP. (in particolare, JSON codificherà un punto di codice usando due escape\u) Se si presuppone che 1 sequenza di escape si traduca in 1 punto di codice, si è condannati a tale testo.

Utilizzo di un parser completo JSON dalla lingua di vostra scelta è notevolmente più robusta:

$ echo '["foo bar \u0144\n"]' | python -c 'import json, sys; sys.stdout.write(json.load(sys.stdin)[0].encode("utf-8"))' 

che è in realtà solo l'alimentazione dei dati a questo breve script python:

import json 
import sys 

data = json.load(sys.stdin) 
data = data[0] # change this to find your string in the JSON 
sys.stdout.write(data.encode('utf-8')) 

da cui è possibile salva come foo.py e chiama come curl ... | foo.py

Un esempio che interromperà la maggior parte degli altri tentativi in ​​questa domanda è "\ud83d\udca3":

% printf '"\\ud83d\\udca3"' | python2 -c 'import json, sys; sys.stdout.write(json.load(sys.stdin)[0].encode("utf-8"))'; echo 

# echo will result in corrupt output: 
% echo -e $(printf '"\\ud83d\\udca3"') 
"������" 
# native2ascii won't even try (this is correct for its intended use case, however, just not ours): 
% printf '"\\ud83d\\udca3"' | native2ascii -encoding utf-8 -reverse 
"\ud83d\udca3" 
+0

Perché diamine dovrei codificare qualcosa per trasformare uno standard in un altro? La ruota era già stata inventata ... –

+1

È curioso che tu lo stia rivisitando dopo quattro anni. Questa risposta non reinventa, come tu intendi, la ruota: infatti usa il parser JSON integrato di Python. Molte delle altre risposte in questo thread tentano di forzare uno strumento non destinato a questo scopo e, come risultato, emetteranno output errati su alcuni input validi. Si consideri il valore con codifica JSON '" \ ud83d \ udca9 "'; sia la soluzione votata più alta che usa 'echo' e la tua soluzione' native2ascii' non elaborerà questo input. – Thanatos

+0

Sono stato informato di alcune attività su questa domanda. D'accordo, che alcune risposte qui fanno schifo, tuttavia, se devo codificare anche 1 riga invece di usare uno strumento già esistente, la chiamerei reinventare la ruota. La tua soluzione è limitata ai contenuti JSON, come tradurrei contenuti non JSON? Ho capito che la tua soluzione funziona per tutti i punti di codice, ma nel mio caso la tua soluzione è esagerata, tuttavia mi piace l'idea di analizzare più di 1 carattere di codice. La risposta accettata attualmente funziona anche per il tuo esempio (tuttavia non è stampato correttamente sul mio terminale, ma il numero di "?" È lo stesso) –

8

utilizzare /usr/bin/printf "\u0160ini\u010di Ho\u0161i - A\u017e sa skon\u010d\u00ed zima" per ottenere la conversione corretta da unicode a utf8.

+1

Una soluzione valida, dato che la domanda è relativa a Linux; solo un heads-up per gli utenti su altre piattaforme: non tutti gli eseguibili esterni 'printf' supportano questo (ad esempio, OS X 10.9.2 non lo fa). – mklement0

+0

FWIW penso che 'printf' sia correlato alla shell corrente che stai usando, es. è considerato uno di quei buildin di shell fantasiosi. E sto eseguendo fish shell 2.7.1 su macOS 10.12.6 e sopra 'printf" \ u965 "' e gli amici funzionano bene per me. ✧ * 0,9 ('ᗜ' *) و✧ *. – Chris

-1

funziona su Windows, dovrebbe funzionare su * nix troppo. Usi pitone 2.

#!/usr/bin/env python 
from __future__ import unicode_literals 
import sys 
import json 
import codecs 

def unescape_json(fname_in, fname_out): 
    with file(fname_in, 'rb') as fin: 
     js = json.load(fin) 
    with codecs.open(fname_out, 'wb', 'utf-8') as fout: 
     json.dump(js, fout, ensure_ascii=False) 

def usage(): 
    print "Converts all \\uXXXX codes in json into utf-8" 
    print "Usage: .py infile outfile" 
    sys.exit(1) 

def main(): 
    try: 
     fname_in, fname_out = sys.argv[1:] 
    except Exception: 
     usage() 

    unescape_json(fname_in, fname_out) 
    print "Done." 

if __name__ == '__main__': 
    main() 
Problemi correlati