2012-01-09 23 views
33

Yo uso curl para obtener algún tipo de respuesta URL, que es la respuesta JSON y que contiene caracteres Unicode-nacionales escapado como \u0144 (ń) y \u00f3 (ó).Cómo convertir uXXXX Unicode UTF-8 utilizando herramientas de la consola en * nix

¿Cómo puedo convertirlos a UTF-8 o cualquier otra codificación para guardar en el archivo?

+1

Véase también Unix y Linux: ** [En bash, ¿cómo puedo convertir un punto de código Unicode \ [0-9A-F \] en el personaje printabale?] (Http: // UNIX .stackexchange.com/questions/12273) ** – hippietrail

Respuesta

26

No sé qué distribución está utilizando, pero debe incluirse uni2ascii.

$ sudo apt-get install uni2ascii 

Sólo depende de libc6, por lo que es una solución ligera (i386 uni2ascii 4,18-2 es 55,0 kB) en Ubuntu!

después utilizarla:

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

podría ser un poco feo, pero echo -e debería hacerlo:

echo -en "$(curl $URL)" 

-e interpreta escapes, -n suprime la nueva línea echo normalmente agregar.

Nota: El escape \u funciona en el bash incorporado echo, pero no /usr/bin/echo.

Como se señaló en los comentarios, esto es bash 4.2+ y 4.2.x tienen un error al manejar 0x00ff/17 valores (0x80-0xff).

+0

No creo que '\ u' sea una secuencia de escape admitida. – cmbuckley

+1

@cbuckley Funciona para mí. – Kevin

+0

¿Es eso zsh por casualidad? En cuyo caso, 's/supported/general supported /' :-) – cmbuckley

18

Suponiendo que el \u siempre es seguido por exactamente 4 dígitos hexadecimales:

#!/usr/bin/perl 

use strict; 
use warnings; 

binmode(STDOUT, ':utf8'); 

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

El binmode pone la salida estándar en modo UTF-8. El comando s... reemplaza cada aparición de \u seguido de 4 dígitos hexadecimales con el carácter correspondiente. El sufijo e hace que el reemplazo se evalúe como una expresión en lugar de tratarse como una cadena; el g dice que se reemplacen todas las ocurrencias en lugar de solo la primera.

Puede guardar lo anterior en un archivo en algún lugar de su $PATH (no olvide el chmod +x). Filtra la entrada estándar (o uno o más archivos nombrados en la línea de comando) a la salida estándar.

+0

simple y eficiente – rupps

+0

nice solution !! Voy a hackear el camino inverso desde [este código] (http://icompile.eladkarako.com/yet-another-javascript-unicode-encodedecode/) más adelante ... –

+0

¿Por qué diablos debería codificar algo para transformarme de un estándar? ¿a otro? La rueda ya estaba inventada ... –

8

No confíe en las expresiones regulares: JSON tiene algunos casos de esquina extraños con \u escapes y puntos de código que no son BMP. (específicamente, JSON codificará un punto de código usando dos\u escapes) Si supone que 1 secuencia de escape se traduce en 1 punto de código, está condenado a dicho texto.

El uso de un analizador completo JSON desde el idioma de su elección es considerablemente más robusto:

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

Eso es realmente sólo la alimentación de los datos de este breve script en 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')) 

desde donde se puede guardar como foo.py y llamar como curl ... | foo.py

Un ejemplo que romperá la mayoría de los otros intentos en esta pregunta es "\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

¿Por qué diablos debería codificar algo para transformar de un estándar a otro? La rueda ya estaba inventada ... –

+1

Es curioso que la estés revisando después de cuatro años. Esta respuesta, como usted supone, no reinventa la rueda: de hecho, usa el analizador JSON incorporado de Python. Muchas de las otras respuestas en este hilo intentan forzar una herramienta no destinada para este propósito, y como resultado, emitirá una salida errónea en algunas entradas válidas. Considere el valor codificado JSON '" \ ud83d \ udca9 "'; tanto la solución más votada usando 'echo' como su solución' native2ascii' no procesará esta entrada. – Thanatos

+0

Me han informado sobre alguna actividad relacionada con esta pregunta. De acuerdo, que algunas respuestas aquí apestan, aún así, si tengo que codificar incluso 1 línea en lugar de usar una herramienta ya existente, la llamaría reinventar la rueda. Su solución está limitada al contenido JSON, ¿cómo traduciría el contenido que no es JSON? Entendí que su solución funciona para todos los puntos de código, pero en mi caso su solución es exagerada, sin embargo me gusta la idea de analizar más de 1 caracteres de punto de código. La respuesta aceptada actual también funciona para su ejemplo (sin embargo, no está impreso correctamente en mi terminal, pero el número de "?" Es el mismo) –

8

uso /usr/bin/printf "\u0160ini\u010di Ho\u0161i - A\u017e sa skon\u010d\u00ed zima" para obtener la conversión adecuada de unicode a utf8.

+1

Una solución válida, dado que la pregunta está relacionada con Linux; solo un aviso para usuarios de otras plataformas: no todos los ejecutables externos de 'printf' son compatibles (por ejemplo, OS X 10.9.2 no). – mklement0

+0

FWIW creo que 'printf' está relacionado con el shell actual que está ejecutando, es decir. se lo considera uno de esos builtins de concha de lujo. Y estoy ejecutando fish shell 2.7.1 en macOS 10.12.6 y el 'printf '\ u965" 'y amigos de arriba funcionan bien para mí. ✧ * .9 ('ᗜ' *) و✧ *. – Chris

-1

funciona en Windows, deben trabajar en * nix también. Utiliza Python 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() 
Cuestiones relacionadas