tr: ubah apostrof menjadi ASCII

11

Saya mencoba untuk mengkonversi Hak Tunggal Quotation Mark ke Apostrophe menggunakan tr.

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

diberi file berkode UTF-8 ayang disebut yang berisi contoh ini:

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

OS X menggunakan BSD trdan menghasilkan hasil yang bagus:

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

Ubuntu menggunakan GNU trdan menghasilkan hasil buruk ini:

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

Bagaimana saya bisa menyelesaikan konversi ini di Ubuntu?

plamtrue
sumber
Juga mencoba: tr $ '\ xE2 \ x80 \ x99' $ '\ x27' <a> b dengan hasil yang sama.
plamtrue
1
Ini bagus untuk mengetahui tanda kutip ASCII dan Unicode
αғsнιη
2
echo It’s easy | perl -CS -Mutf8 -pe "tr/’/'/"
tchrist

Jawaban:

16

Anda dapat mencoba beberapa alat lain, seperti sed:

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

Atau, karena kami sedang melakukan terjemahan sederhana, gunakan yperintah untuk sed:

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

GNUtr mungkin tidak berfungsi karena:

Saat ini trsepenuhnya mendukung hanya karakter byte tunggal. Akhirnya itu akan mendukung karakter multibyte; ketika itu terjadi, -C opsi akan menyebabkannya melengkapi set karakter, sedangkan -c akan menyebabkannya melengkapi set nilai. Perbedaan ini hanya akan menjadi masalah ketika beberapa nilai bukan karakter, dan ini hanya mungkin di lokal menggunakan pengkodean multibyte ketika input berisi kesalahan pengkodean.

Dan merupakan karakter multibyte:

$ echo -n \' | wc -c
1
$ echo -n  | wc -c  
3
muru
sumber
1
sedjauh lebih baik untuk jenis pekerjaan ini.
Kaz Wolfe
2
Untuk menjelaskan bagian terakhir lebih lanjut: tradalah mengganti masing-masing dari tiga byte secara terpisah dengan ', karenanya '''serta urutan rusak di mana ia telah menggantikan dua dari tiga byte dalam karakter yang sama dan . Seharusnya memahami tiga byte sebagai bersama-sama yang berarti satu karakter, dan ganti itu.
deltab
Untuk pemahaman yang baik adalah karakter multibyte juga kita dapat menggunakan tr -c '[:print:][:cntrl:]' '-'perintah untuk mengganti setiap karakter non-cetak , selain karakter kontrol yang valid, dengan a -. Dan Anda akan melihat terjemahan tunggal hingga 3 byte karakter seperti ---. poin bagus untuk karakter multi-byte.
αғsнιη
9

Jika Anda juga ingin mengonversi tanda kutip ganda, dan mungkin karakter lain, Anda bisa menggunakan GNUiconv :

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

The //TRANSLITakhiran mengatakan iconvbahwa untuk karakter luar repertoar pengkodean sasaran (di sini ASCII), dapat menggantikan karakter yang mirip atau urutan otomatis. Tanpa akhiran, iconvakan menyerah begitu menemukan karakter yang tidak dapat diterjemahkan.

Catatan yang //TRANSLITtampaknya merupakan ekstensi GNU: POSIXiconv tidak mendukungnya.

deltab
sumber
+1. Jika Anda mengubah teks dari satu set karakter (atau pengkodean) ke yang lain, mungkin masuk akal untuk menggunakan alat yang dirancang untuk tujuan itu.
RedGrittyBrick
@deltab solusi Anda juga menggantikan tanda kutip ganda yang OP tidak ingin menggantinya.
αғsнιη
@ Kassi Mungkin mereka harus.
gerrit
3

Anda dapat menggunakan salah satu awksolusi ini :

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

Atau

awk '{gsub(/’/, "'"'"'");print}' file
αғsнιη
sumber
0

Gunakan -sopsi tr :

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

Dari man tr :

--truncate-set1
          first truncate SET1 to length of SET2
Skippy le Grand Gourou
sumber
1
solusi Anda juga menggantikan tanda kutip ganda yang OP tidak ingin menggantinya
αғsнιη
Ah, memang, terima kasih sudah menunjukkan ini. Saya akan meninggalkan jawaban ini untuk referensi.
Skippy le Grand Gourou