trに非ASCII(ユニコード)文字を認識させる方法は?


36

ファイル(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

残念ながら、これらのどれも機能しませんでした。

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

回答:


29

そのだ公知の(123456)のGNU実装の制限tr

それはサポートしていないことを限りではありません外国人、英語以外または非ASCII文字が、それはマルチバイト文字をサポートしていないこと。

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

GNU はそれを修正する計画を持っています(参考文献参照)。作業は進行中ですが、まだそこにありません。

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小文字です)。L1

または:

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

1
trに関する情報のため、私はあなたの質問を受け入れました。私は問題を解決し、その解決方法に関する質問を削除しました(したがって、trを探している人は、tr意的な問題ではなく、trについての情報のみを見つけます)。ソリューションが不要になったため、ソリューションも削除していただければ幸いです。
マシューロック

3
@MatthewRock私はそれを保持しましたが、言葉を変えて同じ問題を抱えている人々に役立つだろうので、より一般的にしました。
ステファンシャゼラス

キリル文字が(慣例的に)ISO 8859-5でエンコードされているという考えをどこから得ますか Unicode以外のロシア語のテキストを見たことがありますか?
Incnis Mrsi

9
@IncnisMrsi、ここで重要なのは、ISO 8859-5がこれらのキリル文字を含むシングルバイト文字セットの1つであることです。ここで広く使用されているかどうかは関係ありません。KOI-Rまたはwindow-1251文字セットのロケールがある場合は、必ずそれを使用してください。
ステファンシャゼラス

@IncnisMrsi Web上のロシア語はほとんどの場合、UTF-8(またはWindows-1251)でエンコードされていますが、これは多くのシングルバイトエンコーディングの苦痛を早くから感じたためです。これは、(非機能的な)エンコーディングスイッチャーを備えた古代(1998年頃)のWebページです:sch57.ru/collect
アレックスシュピルキン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.