У меня есть сценарий bash для сравнения имен файлов в разных местах. У них есть специальные символы в именах файлов, которые находятся в двух разных кодировках, поэтому мой сценарий не соответствует этим конкретным файлам.
Могу ли я что-нибудь сделать, чтобы bash соответствовал им?
Они кодируются как utf8 и как TIS-620
Примеры имен файлов в utf8 и TIS-620 соответственно Löffler
и Löffler
пример скрипта:
for i in /dir1/*; do
if [ ! -h "$i" ]; then
[ -d "/dir2/${i##*/}" ]
fi
с использованием unum Я могу эту информацию:
версия utf8 ö
Octal Decimal Hex HTML Character Unicode
0366 246 0xF6 ö "ö" LATIN SMALL LETTER O WITH DIAERESIS
TIS-620 версия ö
Octal Decimal Hex HTML Character Unicode
0157 111 0x6F o "o" LATIN SMALL LETTER O
01410 776 0x308 ̈ "̈" COMBINING DIAERESIS
РЕДАКТИРОВАТЬ:
Я выяснил, что в первую очередь вызывает несоответствие, инструмент, использующий нормализацию UTF. Я все еще хотел бы знать, как сопоставить один и тот же символ в разных кодировках. Другими словами, как я могу использовать встроенную нормализацию UTF для сценариев BASH?
Насколько я понимаю, вам нужно сравнить некоторый «текст», закодированный в кодовой странице TIS -620(Thai )с кодировкой utf8(универсальной )эквивалентной.
Ну, так как самой универсальной кодировкой (, которая будет кодировать столько символов, сколько UTF -32 )является utf8, то нам следует преобразовать в нее самую локальную кодировку TIS -620.
Обычный инструмент преобразования кодировки —iconv
. С помощью этого инструмента вы можете:
$ printf '\xC1' | iconv -f TIS620 -t utf8
ม
И посмотрите (, если ваш терминал принимает utf8 )символ ม. Символ ม
имеет значение C1
, глядя на таблицу в TIS википедии -620.
Или, чтобы «увидеть» байты, составляющие этот символ (в utf8):
$ printf '\xC1' | iconv -f TIS620 -t utf8 | od -vAn -tx1
e0 b8 a1
Какие 3 байта получаются при кодировании символа с кодовой точкой UnicodeU0E21
из формата файла или также на www.utf8 -chartable.de:
U+0E21 ม e0 b8 a1 THAI CHARACTER MO MA
Список кодировок, доступных для TIS620 в iconv::
$ iconv -l | grep 620
TIS-620//
TIS620-0//
TIS620.2529-1//
TIS620.2533-0//
TIS620//
Выберите тот, который соответствует кодировке ваших имен файлов.
Однако мне не удалось найти умляут ö на тайском языке.
Тайская страница TIS620 Или даже (очень старый)перевод тайского языка в ISO/IEC 10646 -1 :1993 не показывает наличие о с умлаутом в тайском языке.
Не могли бы вы повторно -отредактировать свой вопрос?
Предположим, что консоль/терминал настроен на понимание utf8. И давайте создадим три имени файла в каталоге с разными умляутами.
Латинское ö (как одна кодовая точка Unicode )(, представленная как 0xC3 0xB6 в utf8 ).
СТРОЧНАЯ ЛАТИНСКАЯ БУКВА O С ДИЕРЕЗИСОМ (U+00F6)
Латинское ö
$ printf 'L\xC3\xB6ffler'; echo
Löffler
Латинское ö (как буква o, за которой следует диарезис)(0x6F 0xCC 0x88 в utf8 ).
ОБЪЕДИНЕНИЕ ДИАЭРЕЗА (U+0308)
Диэрезис
$ printf 'Lo\xCC\x88ffler'; echo
Löffler
И :Кириллица о с диэрезисом (это 0xD3 0xA7 в utf -8)
СТРОЧНАЯ КИРИЛЛИЧНАЯ БУКВА O С ДИЕРЕЗИСОМ (U+04E7)
Кириллица O с диэрезисом
$ printf 'L\xD3\xA7ffler'; echo
Lӧffler
Чтобы создать три файла с этими именами, вы можете использовать:
$ touch $(printf 'L\xC3\xB6ffler Lo\xCC\x88ffler L\xD3\xA7ffler')
Способ перечисления таких файлов заключается в использовании Glob, который соответствует (только тем файлам ).
В этом случае конечный ffler
появляется для всех файлов.
$ echo *ffler
Löffler Löffler Lӧffler
Какие результаты этого эха можно подробно просмотреть с помощью:
$ echo *ffler | od -vAn -tx1c
4c 6f cc 88 66 66 6c 65 72 20 4c c3 b6 66 66 6c
L o 314 210 f f l e r L 303 266 f f l
65 72 20 4c d3 a7 66 66 6c 65 72 0a
e r L 323 247 f f l e r \n
Что просто отражает тот факт, что все они разные.
Если они назначены позиционным аргументам оболочки:
$ set -- $(echo *ffler)
Мы можем сравнить каждый:
[ "$1" == "$2" ] && echo "Diferent" || echo "Equal"
Однако разумно ожидать, что первое и второе будут эквивалентны.
Но они отличаются способом выполнения «композиции» . 'L\xC3\xB6ffler'
использует составную )форму NFC (.
В 'Lo\xCC\x88ffler'
используется форма NFD (de -, составленная ).
Вы можете использовать uconv(из пакета icu -devtools)для преобразования этих двух форм.
В разложившемся виде:
$ echo *ffler | uconv -x any-nfd | od -vAn -tx1c
4c 6f cc 88 66 66 6c 65 72 20 4c 6f cc 88 66 66
L o 314 210 f f l e r L o 314 210 f f
6c 65 72 20 4c d0 be cc 88 66 66 6c 65 72 0a
l e r L 320 276 314 210 f f l e r \n
В предварительно -составленной форме:
$ echo *ffler | uconv -x any-nfc | od -vAn -tx1c
4c c3 b6 66 66 6c 65 72 20 4c c3 b6 66 66 6c 65
L 303 266 f f l e r L 303 266 f f l e
72 20 4c d3 a7 66 66 6c 65 72 0a
r L 323 247 f f l e r \n
Теперь, если мы установим эти значения в качестве позиционных параметров и сравним их:
$ set -- $( echo *ffler | uconv -x any-nfc | od -vAn -tx1c )
$ [ "$1" == "$2" ] && echo "Diferent" || echo "Equal"
Символ кириллицы не эквивалентен ни одной из форм этого состава.
Если вам нужно преобразовать его, чтобы вы могли сравнить это имя с другими, вам нужен инструмент, который понимает многобайтовые символы -.
$ echo *ffler | sed 's/\xd3\xa7/\xc3\xb6/g' | od -vAn -tx1c
4c 6f cc 88 66 66 6c 65 72 20 4c c3 b6 66 66 6c
L o 314 210 f f l e r L 303 266 f f l
65 72 20 4c c3 b6 66 66 6c 65 72 0a
e r L 303 266 f f l e r \n
И работает только в формате NFC:
$ echo *ffler | uconv -x any-nfc | sed 's/\xd3\xa7/\xc3\xb6/g' | od -vAn -tx1c
4c c3 b6 66 66 6c 65 72 20 4c c3 b6 66 66 6c 65
L 303 266 f f l e r L 303 266 f f l e
72 20 4c c3 b6 66 66 6c 65 72 0a
r L 303 266 f f l e r \n
Теперь эти три имени совершенно одинаковы.
Проясняет ли вышесказанное вашу истинную озабоченность?
Это даже близко?