Em números persas, ۰۱۲۳۴۵۶۷۸۹
é equivalente a 0123456789
dígitos europeus.
Como posso converter o número persa (pol UTF-8
) para ASCII?
Por exemplo, eu quero ۲۱
tornar-se 21
.
bash
unicode
conversion
بارپابابا
fonte
fonte
echo "۰۱۲۳۴۵۶۷۸۹" | iconv -f UTF-8 -t ascii//TRANSLIT
que não lida com isso ...iconv
está aqui apenas para mapear caracteres em codificações diferentes, mas esses são caracteres (números do árabe oriental) que não têm equivalente em ASCII, você pode convertê-los em algo semelhante o suficiente, mas é apenas de sentido único.iconv
era capaz ou não. Eu esperava que o uso//TRANSLIT
ajudasse, mas não ajudou.Respostas:
Podemos tirar vantagem do fato de que o ponto de código UNICODE dos números persas é consecutivo e ordenado de 0 a 9 :
Isso significa que o último dígito hexadecimal É o valor decimal:
Isso torna esse loop simples uma ferramenta de conversão:
Utilizando-o como:
Observe que esse código também pode converter números arábicos e latinos (mesmo se misturados):
fonte
'۰
. Poderia ter sido escrito também como'"۰'
. O motivo é que printf fornecerá o ponto de código UNICODE se o argumento iniciar com uma aspas simples'
ou duplas"
. Pesquisar um pouco antes de este link para o texto "se o personagem principal é uma aspa simples ou de aspas duplas"Como é um conjunto fixo de números, você pode fazer isso manualmente:
(ou usando
tr
, mas ainda não o GNU tr )É necessário definir seu código de idioma como
en_US.utf8
(ou melhor, o código de idioma ao qual o conjunto de caracteres pertence)sed
para reconhecer seu conjunto de caracteres.Com
perl
:fonte
LC_ALL
É necessário definir o que é necessário para que todos os caracteres unicode sejam considerados como talsed
, certo?tr
para esse propósito exato?tr
como ele não funciona em todos os lugares. Lembre-se também de que algumas ferramentas são otimizadas para lidar com bytes, enquanto outras são para lidar com caracteres. No Unicode (especialmente UTF-8), isso faz uma enorme diferença.LC_ALL
.LC_ALL
também não está definido no meu ambiente (masLANG
está definido comoen_GB.UTF-8
). Com o código acima, recebo o erro "sed: 1:" y / ۰۱۲۳۴۵۶۷۸۹ / ... ": as seqüências de transformação não têm o mesmo comprimento".Para Python, existe a
unidecode
biblioteca que lida com essas conversões em geral: https://pypi.python.org/pypi/Unidecode .No Python 2:
No Python 3:
O encadeamento SO em /programming//q/8087381/2261442 pode estar relacionado.
/ edit: Como Wander Nauta apontou nos comentários e como mencionado na página Unidecode, também há uma versão do shell
unidecode
(em/usr/local/bin/
se instalado sobrepip
):fonte
unidecode
que faz o mesmo que o seu trecho de código Python 3. Sóecho '۰۱۲۳۴۵۶۷۸۹' | unidecode
deveria funcionar.pip
ele está lá.unidecode/util.py
- estranho que o Debian não o inclua. (Edit: Ah, mistério resolvido O pacote Debian está desatualizado e mais velhos do que a utilidade..)Uma versão pura do bash:
Já testei na minha máquina Gentoo e funciona.
Feito como um loop, dada a lista de caracteres (de 0 a 9) para converter:
E usado como:
Outra maneira (um exagero) de usar
grep
:fonte
grep
. Na verdade, eu não entendo essa linha, nem por que você não defineresult=0
. Você está sendo excessivamente cauteloso caso$1
contenha outras coisas além dos dígitos farsi?number=${number//۱/1}
etc. e evitariam oecho
egrep
.Como
iconv
não consigo entender isso, a próxima porta de chamada seria usar otr
utilitário:tr
converte um conjunto de caracteres para outro, então simplesmente dizemos para traduzir o conjunto de dígitos farsi para o conjunto de dígitos latinos.EDIT : Como o usuário @cuonglm aponta. Isso requer não-GNU
tr
, por exemplo,tr
em um Mac, e também exige que$LC_CTYPE
esteja definido comoen_US.UTF-8
.fonte
en_US.utf8
.