ファイル(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
残念ながら、これらのどれも機能しません。
Unicodeをどのように理解できますかtr
?
答え1
これは知られている(1、2、サム、4、5、6)GNU実装の制限tr
。
サポートしていないわけではない。外国の、英語ではない、またはASCII以外の文字ですが、マルチバイト文字はサポートされていません。
iso8859-5(文字ごとに1バイト)文字セットとして書き込む場合(ロケールがその文字セットを使用している場合)、これらのキリル文字は正しく処理されますが、問題はASCIIではなくUTF-8文字を使用することです。 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
小文字です。)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
答え2
GNU sedを使用してください(LANG
例:適切な環境変数を含むen_US.UTF-8
)。
% sed 'y/123/abc/; y/āōī/456/' <<< test123ingmāōī
testabcingm456