Управляющие символы ASCII имеют определения из 1960-х годов (фактически предшествующие тому, что вы могли бы считать сетью ). Не все эти управляющие символы используются так, как тогда они были определены для телекоммуникационного оборудования.
В Unix-подобных системах нет необходимости в символе EOF
; никто не используется. Система может сообщать приложениям, сколько байтов находится в файле:
В некоторых других системах (например, в VMS, DOS, Windows) control-Z может действовать как маркер конца файла, поскольку в более ранний версии, система не могла сообщить некоторым приложениям, сколько байтов находится в файле.
В случае VMS ограничение было связано со способом работы среды выполнения C. Приложения на ассемблере могли (и получили) получить файл правильного размера.
Системы Unix в оболочке обычно используют control-D, чтобы сообщить приложению, что достигнут конец ввода (файла), но control-D не сохраняется в файле.
В языке C EOF
специально сделан -1
, чтобы указать, что это недопустимый символ. Стандартный ввод-вывод возвращает EOF
, когда обнаруживается условие конца файла, а не специальный символ.
Между прочим, файлы не обязательно должны заканчиваться символом новой строки (перевод строки 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 )
Установка языкового стандарта на en_US.utf8
(или, лучше сказать, языковой стандарт, к которому принадлежит набор символов) требуется для sed
, чтобы распознать ваш набор символов.
С perl
:
$ echo "۲۱" |
perl -CS -MUnicode::UCD=num -MUnicode::Normalize -lne 'print num(NFKD($_))'
21
Поскольку iconv
не может это понять, следующим портом вызова будет использование утилиты tr
:
$ echo "۲۱" | tr '۰۱۲۳۴۵۶۷۸۹' '0123456789'
21
tr
переводит один набор символов в другой, поэтому мы просто говорим ему перевести набор цифр фарси в набор латинских цифр.
РЕДАКТИРОВАТЬ : как указывает пользователь @cuonglm. Для этого требуется не-GNU tr
, например tr
на Mac, а также требуется, чтобы для $ LC_CTYPE
было установлено значение en_US.UTF- 8
.
Чистая версия 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"
Для 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:
Как указал Вандер Наута в комментариях и как упоминалось на странице Unidecode, существует также версия оболочки unidecode
(в разделе / usr / local / bin /
при установке поверх pip
):
$ echo '۰۱۲۳۴۵۶۷۸۹' | unidecode
0123456789