tr: converte apóstrofo em ASCII


11

Estou tentando converter um aspas simples para um apóstrofo usando tr.

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

dado um arquivo codificado em UTF-8 chamado aque contém este exemplo:

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

O OS X usa o BSD tre produz um bom resultado:

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

O Ubuntu usa o GNU tre produz este resultado desagradável:

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

Como posso realizar essa conversão no Ubuntu?


Também tentei: tr $ '\ xE2 \ x80 \ x99' $ '\ x27' <a> b com os mesmos resultados.
— Plamtrue


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

Respostas:


16

Você pode tentar outra ferramenta, como sed:

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

Ou, como estamos fazendo uma tradução simples, use o ycomando para sed:

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

O GNUtr não funciona presumivelmente porque:

Atualmente, trsuporta totalmente apenas caracteres de byte único. Eventualmente, ele suportará caracteres multibyte; quando isso acontecer, a -C opção fará com que complemente o conjunto de caracteres, enquanto -c fará com que complemente o conjunto de valores. Essa distinção será importante apenas quando alguns valores não forem caracteres, e isso só é possível em locais usando codificações multibyte quando a entrada contiver erros de codificação.

E ’é um caractere multibyte:

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

1
sedé muito melhor para esse tipo de trabalho.
— Kaz Wolfe

2
Para explicar ainda mais a última parte: trestá substituindo cada um dos três bytes separadamente por ', portanto ''', assim como as seqüências quebradas em que ele substituiu dois dos três bytes nos caracteres semelhantes “e ”. Em vez disso, deve entender os três bytes como juntos, significando um caractere e substituí-lo.
— Deltab

Para melhor compreensão, ’é um caractere multibyte e também podemos usar o tr -c '[:print:][:cntrl:]' '-'comando para substituir todos os caracteres não imprimíveis , exceto os caracteres de controle válidos, por a -. E você verá uma ’tradução simples para 3 bytes de caracteres como ---. bom ponto para caracteres de vários bytes.
— αғsнιη

9

Se você também deseja converter aspas duplas e talvez outros caracteres, use o GNUiconv :

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

O //TRANSLITsufixo informa iconvque, para caracteres fora do repertório da codificação de destino (aqui ASCII), ele pode substituir automaticamente caracteres ou seqüências de aparência semelhante. Sem o sufixo, iconvdesistirá assim que encontrar um caracter intraduzível.

Observe que //TRANSLITparece ser uma extensão do GNU: o POSIXiconv não suporta.


+1. Se você estiver convertendo um texto de um conjunto de caracteres (ou codificação) para outro, pode ser sensato usar uma ferramenta projetada para esse fim.
— RedGrittyBrick

@deltab sua solução também substitui aspas duplas que o OP não deseja substituí-las.
— αғsнιη

@KasiyA Talvez devessem.
— Gerrit #

3

Você pode usar uma destas awksoluções:

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

Ou

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

0

Use a -sopção 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
sua solução também substitui aspas duplas que OP não querem substituí-los
— αғsнιη

Ah, de fato, obrigado por apontar isso. Vou deixar esta resposta como referência.
— Skippy le Grand Gourou
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.