パイプラインで複数のtrプロセスを回避するためにtrコマンドを接続することは可能ですか?

パイプラインで複数のtrプロセスを回避するためにtrコマンドを接続することは可能ですか?

複数のtxtファイルがあり、これを小文字、アルファベット順に1行に1語ずつ出力したいと思います。tr次のように、パイプラインで複数のコマンドを使用してこれを実行できます。

tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'

1回のスキャンで完了できますか?これを行うためにCプログラムを書くこともできますがtrsedまたはを使ってawkこれを行う方法があるようですperl

答え1

複数の翻訳を組み合わせることはできますが(ロケール関連セットが重複する複雑な場合を除き)、削除と翻訳を組み合わせることはできません。

<doyle_sherlock_holmes.txt tr -d '[:punct:]' | tr '[:upper:] ' '[:lower:]\n'

より複雑なツールの場合、2 回の呼び出しは 1 回の呼び出しtrより高速になる可能性がありますが、これは入力サイズ、さまざまな文字の割合、ツールの実装trと競合するツール、オペレーティングシステム、コアの数などによって大きく異なります。

答え2

はい。trASCIIロケールでこれを行うことができます。(GNUの場合はとにかくtrこれが唯一の権限です)。 POSIXクラスを使用するか、8進数で各文字のバイト値を参照できます。範囲にわたって変換を分割することもできます。

LC_ALL=C tr '[:upper:]\0-\101\133-140\173-\377' '[:lower:][\n*]' <input

上記のコマンドは、すべての大文字を小文字に変換し、小文字を完全に無視し、他のすべての文字を改行文字に変換します。もちろん、空の行がたくさんあります。この場合、圧着反復スイッチが役に立つかもしれませんが、tr -sto変換と組み合わせて使用​​すると、最終的に大文字も圧着します。これを行うには、次の2番目のフィルタが必要です。[:upper:][:lower:]

LC... tr ... | tr -s \\n

...または...

LC... tr ... | grep .

...結局これを行うよりもはるかに便利になります...

LC_ALL=C tr -sc '[:alpha:]' \\n <input | tr '[:upper:]' '[:lower:]'

...これは、-cアルファベット文字の2つの補数を単一の改行文字に順次圧縮し、パイプの反対側から上から下に変換を実行します。

だからといって、これらの性格の範囲が役に立たないというわけではありません。このような:

tr '\0-\377' '[1*25][2*25][3*25][4*25][5*25][6*25][7*25][8*25][9*25][0*]' </dev/random

...入力バイトをその値のスペクトラム拡散内のすべての数値に変換するので、非常に便利です。無駄にしないで、欲しくないでください。

変換を実行する別の方法はdd

tr '\0-\377' '[A*64][B*64][C*64][D*64]' </dev/urandom |
dd bs=32 cbs=8 conv=unblock,lcase count=1

dadbbdbd
ddaaddab
ddbadbaa
bdbdcadd

タスクと変換を同時にdd実行できるため、ほとんどのタスクをここに任せることもできます。ただし、これは単語ごとのバイト数を正確に予測できる場合、または少なくとも各単語にスペースを事前に入力して予測可能なバイト数を達成できる場合にのみ役立ちます。これは、各ブロック空間の末尾の終わりを占めるからです。unblocklcaseunblock

答え3

以下はいくつかの方法です。

  • GNU grepSum tr: すべての単語を見つけて小文字にします。

    grep -Po '\w+' file | tr '[A-Z]' '[a-z]'
    
  • GNU grepとperl:上記と同じですが、Perlは小文字の変換を処理します。

    grep -Po '\w+' file | perl -lne 'print lc()'
    
  • perl:すべてのアルファベット文字を見つけて小文字で印刷します(@steeldriverに感謝します):

    perl -lne 'print lc for /[a-z]+/ig' file
    
  • sed:文字またはスペース以外のすべての文字を削除し、すべてのアルファベット文字を小文字のバージョンに置き換え、すべてのスペースを改行に置き換えます。これは、すべての空白が空白でタブがないと仮定します。

    sed 's/[^a-zA-Z ]\+//g;s/[a-zA-Z]\+/\L&/g; s/ \+/\n/g' file
    

関連情報