tr: 将撇号转换为 ASCII

pla*_*rue 11 bash unicode utf-8

我想一个转换右单引号一个撇号使用tr

tr "`echo -e '\xE2\x80\x99'`" "`echo -e '\x27'`" < a > b
Run Code Online (Sandbox Code Playgroud)

给定一个名为 UTF-8 编码的文件a,其中包含以下示例:

We’re not a different species
“All alone?” Jeth mentioned.
Run Code Online (Sandbox Code Playgroud)

OS X 使用 BSDtr并产生不错的结果:

We're not a different species
“All alone?” Jeth mentioned.
Run Code Online (Sandbox Code Playgroud)

Ubuntu 使用 GNUtr并产生以下令人讨厌的结果:

We'''re not a different species
''<9C>All alone?''<9D> Jeth mentioned.
Run Code Online (Sandbox Code Playgroud)

如何在 Ubuntu 中完成这种转换?

mur*_*uru 16

您可以尝试一些其他工具,例如sed

$ sed "s/’/'/g" <a
We're not a different species
“All alone?” Jeth mentioned.
Run Code Online (Sandbox Code Playgroud)

或者,由于我们正在做简单的翻译,请使用以下y命令sed

$ sed "y/’/'/" <a
We're not a different species
“All alone?” Jeth mentioned.
Run Code Online (Sandbox Code Playgroud)

GNUtr不工作大概是因为:

目前tr仅完全支持单字节字符。最终它将支持多字节字符;当它这样做时,该-C 选项将使其对字符集进行补充,而-c 将使其对值集进行补充。只有当某些值不是字符时,这种区别才有意义,并且只有在输入包含编码错误时使用多字节编码的语言环境才有可能。

并且是一个多字节字符:

$ echo -n \' | wc -c
1
$ echo -n ’ | wc -c  
3
Run Code Online (Sandbox Code Playgroud)

  • 进一步解释最后一部分:`tr` 分别用 `'` 替换了三个字节中的每一个,因此 `'''` 以及替换了相似字符中三个字节中的两个的损坏序列`“ `和`”`。相反,它应该将三个字节理解为一起表示一个字符,并替换它。 (2认同)

del*_*tab 9

如果您还想转换双引号,也许还有其他字符,您可以使用GNUiconv

$ iconv -f utf-8 -t ascii//translit < a
We're not a different species
"All alone?" Jeth mentioned.
Run Code Online (Sandbox Code Playgroud)

所述//TRANSLIT后缀告诉iconv,对于目标编码(这里ASCII)的剧目以外的字符,它可以自动替代外观相似的字符或序列。没有后缀,iconv一旦发现无法翻译的字符就会放弃。

请注意,这//TRANSLIT似乎是一个 GNU 扩展:POSIXiconv不支持它。