Как преобразовать персидские цифры в UTF-8 в европейские цифры в ASCII?

В персидских цифрах ۰۱۲۳۴۵۶۷۸۹ эквивалентно 0123456789 в европейских цифрах.

Как преобразовать персидское число (в UTF-8 ) в ASCII?

  • Как отобразить управляющие символы (^ C, ^ D, ^ [, ...) по-разному в оболочке
  • Переименование: как присоединить слово или переименовать несколько файлов
  • Добавить 0 в середине имени файла
  • Переключение источника и адресата (или отмена операции mv, cp)
  • Может ли IFS (внутренний разделитель полей) функционировать как отдельный разделитель для нескольких последовательных разделительных символов?
  • Если «bash <file>» работает, почему «source <file>» выдает ошибку?
  • Например, я хочу ۲۱ стать 21 .

  • Получение отказа в доступе при попытке добавить текст в файл с помощью sudo
  • Каковы накладные расходы на использование подоболочек?
  • Как остановить перенаправление в bash
  • Как отложить переменное расширение
  • Bash не равно сравнение строк
  • cp: не может stat `/vol/examples/tutorial/science.txt ': нет такого файла или каталога
  • 5 Solutions collect form web for “Как преобразовать персидские цифры в UTF-8 в европейские цифры в ASCII?”

    Мы можем воспользоваться тем, что кодовая точка UNICODE персидских цифр последовательна и упорядочена от 0 до 9 :

     $ printf '%b' '\U06F'{0..9} ۰۱۲۳۴۵۶۷۸۹ 

    Это означает, что последняя шестнадцатеричная цифра означает десятичное значение:

     $ echo $(( $(printf '%d' "'۲") & 0xF )) 2 

    Это делает этот простой цикл инструментом преобразования:

     #!/bin/bash ( ### Use a locale that use UTF-8 to make the script more reliable. ### Maybe something like LC_ALL=fa_IR.UTF-8 for you?. LC_ALL=en_US.UTF-8 a="$1" while (( ${#a} > 0 )); do # extract the last hex digit from the UNICODE code point # of the first character in the string "$a": printf '%d' $(( $(printf '%d' "'$a") & 15 )) a=${a#?} ## Remove one character from $a done ) echo 

    Используя его как:

     $ sefr.sh ۰۱۲۳۴۵۶۷۸۹ 0123456789 $ sefr.sh ۲۰۱ 201 $ sefr.sh ۲۱ 21 

    Обратите внимание, что этот код также может преобразовывать арабские и латинские цифры (даже если они смешанные):

     $ sefr.sh ۴4٤۵5٥۶6٦۷7٧۸8٨۹9٩ 444555666777888999 $ sefr.sh ٤٧0٠٦7١٣3٥۶٦۷ 4700671335667 

    Поскольку это фиксированный набор чисел, вы можете сделать это вручную:

     $ echo ۲۱ | LC_ALL=en_US.UTF-8 sed -e 'y/۰۱۲۳۴۵۶۷۸۹/0123456789/' 21 

    (или используя tr , но не GNU tr еще)

    Для того, чтобы sed распознал ваши персонажи, требуется установка вашего языка в en_US.utf8 (или лучше для локали, к которой относится набор символов).

    С perl :

     $ echo "۲۱" | perl -CS -MUnicode::UCD=num -MUnicode::Normalize -lne 'print num(NFKD($_))' 21 

    Для Python существует библиотека unidecode которая обрабатывает такие преобразования в целом: https://pypi.python.org/pypi/Unidecode .

    В Python 2:

     >>> from unidecode import unidecode >>> unidecode(u"۰۱۲۳۴۵۶۷۸۹") '0123456789' 

    В Python 3:

     >>> from unidecode import unidecode >>> unidecode("۰۱۲۳۴۵۶۷۸۹") '0123456789' 

    Поток SO на https://stackoverflow.com/q/8087381/2261442 может быть связан.

    / edit: Как указывал Wander Nauta в комментариях, и, как упоминалось на странице Unidecode, есть также версия оболочки unidecode/usr/local/bin/ if installed over pip ):

     $ echo '۰۱۲۳۴۵۶۷۸۹' | unidecode 0123456789 

    Чистая версия bash:

     #!/bin/bash number="$1" number=${number//۱/1} number=${number//۲/2} number=${number//۳/3} number=${number//۴/4} number=${number//۵/5} number=${number//۶/6} number=${number//۷/7} number=${number//۸/8} number=${number//۹/9} number=${number//۰/0} echo "Result is $number" 

    Испытали в моей машине Gentoo, и она работает.

     ./convert ۱۳۲ Result is 132 

    Выполнен как цикл, заданный список символов (от 0 до 9) для преобразования:

     #!/bin/bash conv() ( LC_ALL=en_US.UTF-8 local n="$2" for ((i=0;i<${#1};i++)); do n=${n//"${1:i:1}"/"$i"} done printf '%s\n' "$n" ) conv "۰۱۲۳۴۵۶۷۸۹" "$1" 

    И используется как:

     $ convert ۱۳۲ 132 

    Другой способ (довольно избыточный) с использованием grep :

     #!/bin/bash nums=$(echo "$1" | grep -o .) result=() for i in $nums do case $i in ۱) result+=1 ;; ۲) result+=2 ;; ۳) result+=3 ;; ۴) result+=4 ;; ۵) result+=5 ;; ۶) result+=6 ;; ۷) result+=7 ;; ۸) result+=8 ;; ۹) result+=9 ;; ۰) result+=0 ;; esac done echo "Result is $result" 

    Поскольку iconv не может казаться, что это будет выглядеть, следующим портом вызова будет использование утилиты tr :

     $ echo "۲۱" | tr '۰۱۲۳۴۵۶۷۸۹' '0123456789' 21 

    tr переводит один набор символов в другой, поэтому мы просто скажем, чтобы он перевел набор цифр фарси на набор латинских цифр.

    EDIT : Как указывает пользователь @cuonglm. Для этого требуется не-GNU tr , например tr на Mac, и для этого также требуется, чтобы $LC_CTYPE был установлен в en_US.UTF-8 .

    Linux и Unix - лучшая ОС в мире.