заставить сценарий bash сопоставлять имена файлов со специальными символами в разных кодировках

У меня есть сценарий 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?

0
03.08.2017, 14:25
1 ответ

Насколько я понимаю, вам нужно сравнить некоторый «текст», закодированный в кодовой странице 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. И давайте создадим три имени файла в каталоге с разными умляутами.

  1. Латинское ö (как одна кодовая точка Unicode )(, представленная как 0xC3 0xB6 в utf8 ).
    СТРОЧНАЯ ЛАТИНСКАЯ БУКВА O С ДИЕРЕЗИСОМ (U+00F6)
    Латинское ö

    $ printf 'L\xC3\xB6ffler'; echo
    Löffler
    
  2. Латинское ö (как буква o, за которой следует диарезис)(0x6F 0xCC 0x88 в utf8 ).
    ОБЪЕДИНЕНИЕ ДИАЭРЕЗА (U+0308)
    Диэрезис

    $ printf 'Lo\xCC\x88ffler'; echo
    Löffler
    
  3. И :Кириллица о с диэрезисом (это 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

Теперь эти три имени совершенно одинаковы.

Проясняет ли вышесказанное вашу истинную озабоченность?
Это даже близко?

0
28.01.2020, 04:44

Теги

Похожие вопросы