grep 或 sed 无法识别某些 UTF-8 字符

grep 或 sed 无法识别某些 UTF-8 字符

尝试确定文件中的所有字符。

该文件sample包括:

a eɪ
abandon əˈbændən
ability əˈbɪləti
able ˈeɪbəl
able ˈeɪbl
abortion əˈbɔrʃən
abortion əˈbɔrʃn
about əˈbaʊt
above əˈbʌv
abroad əˈbrɔd

确认区域设置正确:

$ echo $LANG

en_US.UTF-8

获取第二个字段的命令,按字符分割,然后计算有多少个:

$ cat sample | awk '{print $2}' | grep -o . | sort | uniq -c | sort -n

  1 a
  1 æ
  1 i
  1 v
  2 d
  2 t
  3 e
  3 l
  3 ɔ
  3 r
  4 n
  9 b
 11 ə
 17 ɪ

ʃ和在哪里ˈ?他们没有组合字符或任何特殊的东西。请注意,其他 UTF-8 字符将被拉出:例如ɔə和。ɪ

BTW using 的sed 's/\(.\)/\1\n/g'结果几乎与 相同grep -o .,只是它添加了一行“\n”。

我有什么遗漏的吗? grep 有隐藏的 UTF-8 选项吗?

如果重要的话我正在使用Ubuntu 12.04.2 LTS.

答案1

问题在于sortuniq正在使用区域设置的排序规则信息。关闭两个命令的区域设置是有效的:

cat sample | awk '{print $2}' | grep -o . | LC_ALL=C sort | LC_ALL=C uniq -c | sort -n
      1 ʊ
      1 ʌ
      1 a
      1 æ
      1 i
      1 v
      2 ʃ
      2 d
      2 t
      3 e
      3 l
      3 ɔ
      3 r
      4 ɪ
      4 n
      9 ˈ
      9 b
     11 ə

答案2

但是,通过使用“C”语言环境,您会失去人工整理(例如使“a”和“A”等效)。

如果您需要整理和处理 glibc 语言环境数据未处理的某些字符;您可以通过扩展默认排序规则来创建自己的区域设置。

您可以将当前语言环境的定义(例如 /usr/share/i18n/locales/en_US )复制到另一个名称。然后编辑它,在 LC_COLLATE 部分有:

LC_COLLATE
copy "iso14651_t1"

reorder-after <e>
<U0259> <e>;<PCL>;<MIN>;IGNORE
reorder-after <s>
<U0283> <s>;<PCL>;<MIN>;IGNORE
reorder-end

END LC_COLLATE

编译它:localedef -f ./yourmodifiedfile -t UTF-8 ./someplace 然后你可以使用LC_ALL=./someplace而不是LC_ALL=C

如果您想定期使用它,请将创建的目录与其他标准区域设置(通常是 /usr/share/locale 或 /usr/lib/locale )放在一起,并以标准方式命名(例如,如果它基于 en_US 您例如,可以将其命名为“en_US@IPA”,然后您可以将语言环境设置为永久 LC_COLLATE=en_US@IPA(请注意,如果您想单独定义某些 LC_* 变量,则不得定义 LC_ALL)。

另请注意,U+02C8 是一个修饰符,因此在排序规则中应正确地被忽略。但如果您需要将其作为单独的字符处理,则可以使用它(ascii 单引号与 U+02C8 相同(用于整理视图),因为这就是它经常键入的方式):

# defines a handy symbol, to group together similar chars
collating-symbol <'>

# define 
reorder-after <z>
<'>

reorder-after <e>
<U0259> <e>;<PCL>;<MIN>;IGNORE
reorder-after <s>
<U0283> <s>;<PCL>;<MIN>;IGNORE
reorder-after <'>
<U0027> <'>;<BAS>;IGNORE;IGNORE
<U02C8> <'>;<PCL>;IGNORE;IGNORE

reorder-end

行是:<unicode value> <1st level>;<2d level>;<3d level>;<4th level> 级别是用于对它们进行排序的级别。

我认为(但没有尝试过,我把它作为一个练习:))如果你只定义最后一个级别,它将在排序时表现得大部分被忽略,但从 uniq 的角度来看仍然“不同”(只要链我认为所有级别都是独一无二的,角色也是独一无二的)。

通常第一级是分组符号,就像所有类似 e 的字母一样。第二级通常用于基本字符,还有其他几个符号用于各种重音版本,并且(特殊?)用于“特殊”。 3d 级别通常用于区分大写和小写之类的东西。

相关内容