utf-8编码混淆文件通配和grep'ing?

时间:2010-09-21 22:06:55

标签: encoding utf-8 grep filenames

我正在玩bash,体验utf-8编码。我是unicode的新手。 以下命令(以及它们的输出)让我感到惊讶:

  

$ locale
  LANG = “fr_FR.UTF-8”
  LC_COLLATE = “fr_FR.UTF-8”
  LC_CTYPE = “fr_FR.UTF-8”
  LC_MESSAGES = “fr_FR.UTF-8”
  LC_MONETARY = “fr_FR.UTF-8”
  LC_NUMERIC = “fr_FR.UTF-8”
  LC_TIME = “fr_FR.UTF-8”
  LC_ALL =
  $ printf'1 \né\ n12 \ n123 \ n'| egrep'^(。| ...)$'
  1
  é
  12个
  $ touch1é12123
  $ ls | egrep'^(。| ...)$'
  1
  123

确定。两个egrep过滤具有一个或三个字符的行。它们的输入非常相似,但输出与字符é不同。有什么解释吗?

有关我的环境的更多详情:

  

$ uname -a
  Darwin macbook-pro-de-admin-6.local 10.4.0 Darwin Kernel Version 10.4.0:Fri Apr 23 18:28:53 PDT 2010; root:xnu-1504.7.4~1 / RELEASE_I386 i386
  $ egrep -V
  egrep(GNU grep)2.5.1

     

版权所有1988,1992-1999,2000,2001自由软件基金会   这是免费软件;查看复制条件的来源。没有   保证;甚至不适用于适销性或特定用途的适用性。

1 个答案:

答案 0 :(得分:2)

任何可变长度编码都会混淆不知道编码的工具,并在使用单字符通配符时考虑字节而不是字符(因为该工具假定byte =字符)。如果使用文字字符,那么对于UTF-8,它无关紧要,因为UTF-8的结构会阻止字符中间的匹配(假设编码正确)。

至少某些版本的grep应该是UTF-8识别的,根据http://mailman.uib.no/public/corpora/2006-December/003760.html,GNU grep 2.5.1及更高版本包含在那里,只要适当的LANG是组。但是,如果您使用旧版本或GNU grep以外的其他版本,则可能是您的问题的原因,因为é是一个双字节字符(0xC3 0xA9)。

编辑:根据你最近的评论,你的grep可能是支持Unicode的,但它不会执行任何类型的Unicode normalization(说实话,我真的没想到它。)

0x65 0xCC 0x81是e,后跟COMBINING ACUTE ACCENT (U+0301)。这实际上是两个字符,但由于组合字符的语义,它被渲染为一个字符。这会导致grep将其检测为两个字符;一个用于e,一个用于重音。

分解的Unicode似乎可能是文件名实际存储在文件系统中的方式 - 否则,您可以存储的文件出于所有意图和目的,具有完全相同的名称,但仅在组合使用方面有所不同字符。