ファイル(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を理解しますか?
承認された回答:
これは、tr
のGNU実装の既知の(1、2、3、4、5、6)制限です。 。
外国をサポートしていないほどではありません 、非英語または非ASCII文字ですが、マルチバイト文字はサポートされていません。
これらのキリル文字は、iso8859-5(文字あたり1バイト)の文字セットで記述されている場合(およびロケールでその文字セットが使用されている場合)は問題なく処理されますが、問題は、非ASCIIでUTF-8を使用していることです。文字は2バイト以上でエンコードされます。
GNUはそれを修正する計画を持っており(も参照)、作業は進行中ですが、まだそこにはありません。
FreeBSDまたはSolaristr
問題はありません。
それまでの間、tr
のほとんどのユースケースでは 、マルチバイト文字をサポートするGNUSedまたはGNUawkを使用できます。
たとえば、あなたの:
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