我正在尝试从文件中删除一些字符(UTF-8).我正在为此目的使用tr:
tr -cs '[[:alpha:][:space:]]' ' '
文件包含一些外来字符(如“Латвийская”或“àé”). tr似乎并不理解它们:它将它们视为非alpha并将其删除.
我尝试过更改一些语言环境设置:
LC_CTYPE=C LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' '
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' '
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=ru_RU.UTF-8 tr -cs '[[:alpha:][:space:]]' ' '
不幸的是,这些都没有奏效.
如何让tr理解Unicode?
解决方法:
这是tr的GNU实现的已知(1,2,3,4,5,6)限制.
它没有那么多,它不支持外来的,非英语的或非ASCII的字符,但它不支持多字节字符.
如果用iso8859-5(每个字符的单字节)字符集(并且您的语言环境使用该字符集)写入,那些西里尔字符将被处理好,但您的问题是您使用的是非ASCII的UTF-8字符以2个或更多字节编码.
GNU得到了a plan(见also)来解决这个问题,工作正在进行中,但还没有.
FreeBSD或Solaris tr没有问题.
同时,对于tr的大多数用例,您可以使用已经国际化的GNU sed或GNU awk.
例如,你的:
tr -cs '[[:alpha:][:space:]]' ' '
可写:
gsed -E 's/( |[^[:space:][:alpha:]])+/ /'
要么:
gawk -v RS='( |[^[:space:][:alpha:]])+' '{printf "%s", sep $0; sep=" "}'
要在大小写之间进行转换(tr'[:upper:]”[:lower:]’):
gsed 's/[[:upper:]]/\l&/g'
(l是小写L,而不是1位数).
要么:
gawk '{print tolower($0)}'
为了便于携带,perl是另一种选择:
perl -Mopen=locale -pe 's/([^[:space:][:alpha:]]| )+/ /g'
perl -Mopen=locale -pe '$_=lc$_'
如果您知道数据可以用单字节字符集表示,那么您可以在该字符集中处理它:
(export LC_ALL=ru_RU.iso88595
iconv -f utf-8 |
tr -cs '[:alpha:][:space:]' ' ' |
iconv -t utf-8) < Russian-file.utf8
标签:linux,unicode,text-processing,tr
来源: https://codeday.me/bug/20190808/1623736.html