Dalam angka Persia, ۰۱۲۳۴۵۶۷۸۹
sama dengan 0123456789
angka di Eropa.
Bagaimana saya bisa mengonversi nomor Persia UTF-8
menjadi ASCII?
Misalnya, saya ingin ۲۱
menjadi 21
.
bash
unicode
conversion
بارپابابا
sumber
sumber
echo "۰۱۲۳۴۵۶۷۸۹" | iconv -f UTF-8 -t ascii//TRANSLIT
tidak menanganinya ...iconv
ini hanya di sini untuk memetakan karakter dalam pengkodean yang berbeda, tetapi ini adalah karakter (angka Arab Timur) yang tidak memiliki padanan dalam ASCII, Anda bisa mengonversinya menjadi sesuatu yang cukup serupa tetapi hanya satu arah.iconv
yang mampu dan tidak mampu dilakukan. Saya berharap menggunakan itu//TRANSLIT
akan membantu, tetapi ternyata tidak.Jawaban:
Kita dapat memanfaatkan fakta bahwa titik kode UNICODE angka Persia berturut - turut dan dipesan dari 0 hingga 9 :
Itu berarti bahwa digit hex terakhir adalah nilai desimal:
Itu membuat loop sederhana ini alat konversi:
Menggunakannya sebagai:
Perhatikan bahwa kode ini juga dapat mengonversi angka Arab dan Latin (bahkan jika dicampur):
sumber
'۰
. Itu bisa ditulis juga sebagai'"۰'
. Alasannya adalah printf akan memberikan titik kode UNICODE jika argumen dimulai dengan penawaran tunggal'
atau penawaran ganda"
. Cari sedikit sebelum tautan ini untuk teks "Jika karakter utama adalah kutipan tunggal atau kutipan ganda"Karena ini adalah kumpulan angka yang tetap, Anda dapat melakukannya dengan tangan:
(atau menggunakan
tr
, tetapi belum GNU tr )Menyetel lokal Anda ke
en_US.utf8
(atau lebih baik ke lokal yang set karakternya milik) diperlukan untuksed
mengenali set karakter Anda.Dengan
perl
:sumber
LC_ALL
diperlukan agar setiap karakter unicode tunggal juga akan dianggap seperti itu olehsed
, kan?tr
untuk tujuan yang tepat ini?tr
bagaimana itu tidak berfungsi di mana-mana Juga perlu diingat bahwa beberapa alat dioptimalkan untuk menangani byte, sementara yang lain untuk berurusan dengan karakter, dengan Unicode (terutama UTF-8) ini membuat perbedaan besar.LC_ALL
.LC_ALL
juga tidak diatur di lingkungan saya (tetapiLANG
diatur keen_GB.UTF-8
). Dengan kode di atas, saya mendapatkan kesalahan "sed: 1:" y / ۰۱۲۳۴۵۶۷۸۹ / ... ": mengubah string tidak sama panjangnya".Untuk Python ada
unidecode
perpustakaan yang menangani konversi seperti itu secara umum: https://pypi.python.org/pypi/Unidecode .Dengan Python 2:
Dengan Python 3:
Utas SO di /programming//q/8087381/2261442 mungkin terkait.
/ edit: Seperti yang ditunjukkan oleh Wander Nauta dalam komentar dan seperti yang disebutkan pada halaman Unidecode, ada juga versi shell
unidecode
(di bawah/usr/local/bin/
jika diinstalpip
):sumber
unidecode
yang melakukan hal yang sama dengan cuplikan Python 3 Anda. Hanyaecho '۰۱۲۳۴۵۶۷۸۹' | unidecode
harus bekerja.pip
di sana.unidecode/util.py
- aneh bahwa Debian tidak memasukkannya. (Sunting: Ah, misteri terpecahkan. Paket Debian kedaluwarsa dan lebih tua dari utilitas.)Versi bash murni:
Telah diuji di mesin Gentoo saya dan berhasil.
Dilakukan sebagai loop, diberi daftar karakter (dari 0 hingga 9) untuk dikonversi:
Dan digunakan sebagai:
Cara lain (agak berlebihan) menggunakan
grep
:sumber
grep
. Sebenarnya, saya tidak mengerti kalimat itu, atau mengapa Anda tidak mengaturnyaresult=0
. Apakah Anda terlalu berhati-hati seandainya$1
berisi hal-hal lain selain digit Farsi?number=${number//۱/1}
dll, dan akan menghindariecho
dangrep
.Karena
iconv
sepertinya tidak bisa melakukan ini, porta panggilan selanjutnya adalah menggunakantr
utilitas:tr
menerjemahkan satu set karakter ke yang lain, jadi kami hanya mengatakannya untuk menerjemahkan set angka Farsi ke set angka Latin.EDIT : Seperti yang ditunjukkan pengguna @cuonglm. Ini memerlukan non-GNU
tr
, misalnya padatr
pada Mac, dan itu juga mengharuskan$LC_CTYPE
diatur keen_US.UTF-8
.sumber
en_US.utf8
.