Cyfry perskie ۰۱۲۳۴۵۶۷۸۹
odpowiadają 0123456789
cyfrom europejskim.
Jak przekonwertować liczbę perską (in UTF-8
) na ASCII?
Na przykład chcę ۲۱
zostać 21
.
bash
unicode
conversion
بارپابابا
źródło
źródło
echo "۰۱۲۳۴۵۶۷۸۹" | iconv -f UTF-8 -t ascii//TRANSLIT
sobie z tym nie poradzi ...iconv
właśnie tutaj jest mapowanie znaków w różnych kodowaniach, ale są to znaki (cyfry wschodnio arabskie), które nie mają odpowiednika w ASCII, możesz po prostu przekonwertować je na coś podobnego, ale jest to tylko jednokierunkowe.iconv
jest w stanie, a co nie. Miałem nadzieję, że//TRANSLIT
to pomoże, ale tak nie było.Odpowiedzi:
Możemy skorzystać z faktu, że punkt kodowy UNICODE liczb perskich jest następujący i uporządkowany od 0 do 9 :
Oznacza to, że ostatnia cyfra szesnastkowa JEST wartością dziesiętną:
To sprawia, że ta prosta pętla jest narzędziem do konwersji:
Używając go jako:
Pamiętaj, że ten kod może również konwertować cyfry arabskie i łacińskie (nawet jeśli są mieszane):
źródło
'۰
. Mógłby być również napisany jako'"۰'
. Powodem jest to, że printf poda kod UNICODE, jeśli argument zaczyna się od pojedynczego cudzysłowu'
lub podwójnego cudzysłowu"
. Wyszukaj trochę przed tym linkiem tekst „Jeśli wiodącym znakiem jest pojedynczy lub podwójny cudzysłów”Ponieważ jest to stały zestaw liczb, możesz to zrobić ręcznie:
(lub używając
tr
, ale jeszcze nie GNU tr )Ustawienie twojego locale na
en_US.utf8
(lub lepiej na locale, do którego należy zestaw znaków) jest wymaganesed
do rozpoznania twojego zestawu znaków.Z
perl
:źródło
LC_ALL
jest konieczne, aby każdy pojedynczy znak Unicode był również traktowany jako takised
, prawda?tr
tego właśnie w tym celu?tr
tego, jak to nie działa wszędzie. Pamiętaj również, że niektóre narzędzia są zoptymalizowane do obsługi bajtów, podczas gdy inne do obsługi znaków, z Unicode (szczególnie UTF-8) robi to ogromną różnicę.LC_ALL
.LC_ALL
nie jest również ustawiony w moim środowisku (aleLANG
jest ustawiony naen_GB.UTF-8
). Przy powyższym kodzie pojawia się błąd „sed: 1:„ y / ۰۱۲۳۴۵۶۷۸۹ / ... ”: łańcuchy transformacji nie są tej samej długości”.W przypadku Python istnieje
unidecode
biblioteka, która ogólnie obsługuje takie konwersje: https://pypi.python.org/pypi/Unidecode .W Python 2:
W Pythonie 3:
Wątek SO na /programming//q/8087381/2261442 może być powiązany.
/ edit: Jak zauważył Wander Nauta w komentarzach i jak wspomniano na stronie Unidecode, istnieje również wersja powłoki
unidecode
(poniżej,/usr/local/bin/
jeśli została zainstalowanapip
):źródło
unidecode
co nie jest zaskoczeniem), które działa tak samo jak twój fragment kodu w Pythonie 3. Po prostuecho '۰۱۲۳۴۵۶۷۸۹' | unidecode
powinno działać.pip
go tam.unidecode/util.py
- dziwne, że Debian go nie zawiera. (Edycja: Ach, zagadka rozwiązana. Pakiet Debiana jest nieaktualny i starszy niż narzędzie.)Wersja czysto bashowa:
Przetestowałem na moim komputerze Gentoo i działa.
Wykonano jako pętlę, biorąc pod uwagę listę znaków (od 0 do 9) do konwersji:
I używany jako:
Innym (raczej przesadnym) sposobem jest użycie
grep
:źródło
grep
. W rzeczywistości nie rozumiem tej linii ani dlaczego jej nie ustawiłeśresult=0
. Czy jesteś zbyt ostrożny, jeśli$1
zawiera inne rzeczy niż cyfry farsi?number=${number//۱/1}
itd., I uniknąćecho
igrep
.Ponieważ
iconv
wydaje się, że to nie przeszkadza, następnym portem połączenia byłoby użycietr
narzędzia:tr
tłumaczy jeden zestaw znaków na inny, więc po prostu mówimy mu, aby przetłumaczył zestaw cyfr farsi na zestaw cyfr łacińskich.EDYCJA : Jak wskazuje użytkownik @cuonglm. Wymaga to systemu innego niż GNU
tr
, na przykładtr
na komputerze Mac, i również wymaga$LC_CTYPE
ustawieniaen_US.UTF-8
.źródło
en_US.utf8
.