tr: convierte el apóstrofe a ASCII


11

Estoy tratando de convertir una comilla simple a un apóstrofe usando tr.

tr "`echo -e '\xE2\x80\x99'`" "`echo -e '\x27'`" < a > b

dado un archivo codificado UTF-8 llamado aque contiene este ejemplo:

Were not a different species
All alone?” Jeth mentioned.

OS X usa el BSD try produce un buen resultado:

We're not a different species
“All alone?” Jeth mentioned.

Ubuntu usa GNU try produce este desagradable resultado:

We'''re not a different species
''<9C>All alone?''<9D> Jeth mentioned.

¿Cómo puedo lograr esta conversión en Ubuntu?


También probé: tr $ '\ xE2 \ x80 \ x99' $ '\ x27' <a> b con los mismos resultados.
plamtrue


2
echo It’s easy | perl -CS -Mutf8 -pe "tr/’/'/"
tchrist

Respuestas:


16

Puedes probar alguna otra herramienta, como sed:

$ sed "s/’/'/g" <a
We're not a different species
“All alone?” Jeth mentioned.

O, como estamos haciendo una traducción simple, use el ycomando para sed:

$ sed "y/’/'/" <a
We're not a different species
“All alone?” Jeth mentioned.

GNUtr no funciona presumiblemente porque:

Actualmente trsolo admite caracteres de un solo byte. Eventualmente admitirá caracteres multibyte; cuando lo haga, la -C opción hará que complemente el conjunto de caracteres, mientras que -c hará que complemente el conjunto de valores. Esta distinción solo importará cuando algunos valores no sean caracteres, y esto solo es posible en configuraciones regionales que usan codificaciones multibyte cuando la entrada contiene errores de codificación.

Y es un personaje multibyte:

$ echo -n \' | wc -c
1
$ echo -n  | wc -c  
3

1
sedes mucho mejor para este tipo de trabajo.
Kaz Wolfe el

2
Para explicar más la última parte: trestá reemplazando cada uno de los tres bytes por separado con ', por '''lo tanto , así como las secuencias rotas donde ha reemplazado dos de los tres bytes en los caracteres similares y . En su lugar, debe comprender los tres bytes como si significaran un carácter, y reemplazarlos en su lugar.
deltab

Para entender bien, es un carácter multibyte, también podemos usar el tr -c '[:print:][:cntrl:]' '-'comando para reemplazar todos los caracteres que no se imprimen , que no sean caracteres de control válidos, con a -. Y verá una traducción única a 3 bytes de caracteres como ---. Buen punto para el carácter de varios bytes.
αғsнιη

9

Si también desea convertir las comillas dobles, y quizás otros caracteres, puede usar GNUiconv :

$ iconv -f utf-8 -t ascii//translit < a
We're not a different species
"All alone?" Jeth mentioned.

El //TRANSLITsufijo dice iconvque para caracteres fuera del repertorio de la codificación de destino (aquí ASCII), puede sustituir automáticamente caracteres o secuencias de aspecto similar. Sin el sufijo, se iconvrendirá tan pronto como encuentre un personaje intraducible.

Tenga en cuenta que //TRANSLITparece ser una extensión de GNU: POSIXiconv no lo admite.


+1. Si está convirtiendo un texto de un conjunto de caracteres (o codificación) a otro, puede ser sensato usar una herramienta diseñada para ese propósito.
RedGrittyBrick

@deltab su solución también reemplaza las comillas dobles que OP no quiere reemplazar.
αғsнιη

@KasiyA Quizás deberían hacerlo.
gerrit

3

Puede usar una de estas awksoluciones:

awk '{gsub(/\xE2\x80\x99/, "\x27");print}' file # with Hex ASCII code

awk '{gsub(/’/, "\x27");print}' file

awk '{gsub(/\342\200\231/, "\47");print}'  file # with Octal ASCII code

awk '{gsub(/’/, "\47");print}' file

O

awk '{gsub(/’/, "'"'"'");print}' file

0

-sOpción de uso de tr :

$ echo "We’re not a different species"|tr -s "’" "'"
We're not a different species

De man tr :

--truncate-set1
          first truncate SET1 to length of SET2

1
su solución también reemplaza las comillas dobles que OP no quiere reemplazarlas
αғsнιη

Ah, de hecho, gracias por señalar esto. Dejaré esta respuesta como referencia.
Skippy le Grand Gourou
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.