强制 bash 脚本将文件名与不同编码中的特殊字符进行匹配

强制 bash 脚本将文件名与不同编码中的特殊字符进行匹配

我有一个 bash 脚本来比较不同位置的文件名。它们的文件名中有特殊字符,采用两种不同的编码,因此我的脚本与这些特定文件不匹配。

我能做些什么让 bash 匹配它们吗?

它们分别编码为 utf8 和 TIS-620 示例文件名Löffler,以及Löffler

脚本示例:

for i in /dir1/*; do
if [ ! -h "$i" ]; then
[ -d "/dir2/${i##*/}" ]
fi

使用乌努姆我可以得到这些信息:

ö 的 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 标准化的工具。我还是想知道如何匹配不同编码中的相同字符。另一种说法是,如何对 BASH 脚本内联使用 UTF 规范化?

答案1

我认为您需要比较编码中的一些“文本”TIS-620 的代码页(泰语)与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

使用 Unicode 代码点编号对字符进行编码时产生的 3 个字节是多少U0E21 从文件格式或者,也网址:www.utf8-chartable.de

U+0E21  ม   e0 b8 a1    THAI CHARACTER MO MA

iconv 中 TIS620 可用的编码列表为:

$ iconv -l | grep 620
TIS-620//
TIS620-0//
TIS620.2529-1//
TIS620.2533-0//
TIS620//

选择与您的文件名编码相匹配的一种。


但是,我找不到元音变音 ö泰语。
泰国TIS620页面 或者甚至是(非常古老的)泰语翻译为 ISO/IEC 10646-1:1993不要显示泰语中存在带元音变音的 o。

您能重新编辑您的问题吗?


关于元音变音

假设控制台/终端配置为理解 utf8。并且,让我们在一个目录中创建三个具有不同变音符号的文件名。

  1. 拉丁语 ö (作为一个 unicode 代码点)(在 utf8 中表示为 0xC3 0xB6)。
    带分音符的拉丁文小写字母 O (U+00F6)
    拉丁语 ö

    $ printf 'L\xC3\xB6ffler'; echo
    Löffler
    
  2. 拉丁语 ö (字母 o 后跟分音符)(在 utf8 中为 0x6F 0xCC 0x88)。
    组合分音法 (U+0308)
    分音

    $ printf 'Lo\xCC\x88ffler'; echo
    Löffler
    
  3. 并且:带分音符的西里尔字母 o(在 utf-8 中为 0xD3 0xA7)
    带分音符的西里尔小写字母 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

这只是反映了每个人都是不同的事实。

如果它们被分配给 shell 的位置参数:

$ set -- $(echo *ffler)

我们可以对每一项进行比较:

[ "$1" == "$2" ] && echo "Diferent" || echo "Equal"

然而,可以合理地预期第一个和第二个是等效的。
但它们的不同之处在于“构图”的完成方式
使用'L\xC3\xB6ffler'NFC(组合)形式。
使用'Lo\xCC\x88ffler'NFD(分解)形式。

您可以使用 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"

cyrylic 特征并不等同于任何这种构图形式。
如果您需要转换它,以便可以将该名称与其他名称进行比较,则需要一个能够理解多字节字符的工具。

$ 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

现在这三个名字一模一样。

以上内容是否澄清了您真正的担忧?
还接近吗?

相关内容