web-dev-qa-db-ja.com

trに非ASCII(Unicode)文字を認識させる方法は?

ファイル(UTF-8)から一部の文字を削除しようとしています。私はこの目的のためにtrを使用しています:

tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat 

ファイルにいくつかの外来文字(「Латвийская」や「àé」など)が含まれています。 trはそれらを理解していないようです:それらを非アルファとして扱い、削除します。

ロケール設定の一部を変更しようとしました:

LC_CTYPE=C LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=ru_RU.UTF-8 tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat

残念ながら、どれもうまくいきませんでした。

trにUnicodeを理解させるにはどうすればよいですか?

36
MatthewRock

それは既知です( 12 、、 45 、- 6 )GNU trの実装の制限。

foreign、英語以外の文字、またはASCII以外の文字はサポートしていませんが、マルチバイト文字はサポートしていません。 。

これらのキリル文字は、iso8859-5(文字あたり1バイト)文字セット(およびロケールがその文字セットを使用していた)で記述されていれば問題なく処理されますが、問題は、ASCII以外の場所でUTF-8を使用していることです。文字は2バイト以上にエンコードされます。

GNUはそれを修正するために プラン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$_'

データが1バイト文字セットで表現できることがわかっている場合は、その文字セットで処理できます。

(export LC_ALL=ru_RU.iso88595
 iconv -f utf-8 |
   tr -cs '[:alpha:][:space:]' ' ' |
   iconv -t utf-8) < Russian-file.utf8
29