Bash文字列作業速度とパイプ

Bash文字列作業速度とパイプ

md5 チェックサムとファイル名でいっぱいのファイルがあります。各行に対していくつかの処理を実行する必要があるため、次の点に注意してください。

  • チェックサムとは何ですか
  • ファイル名は何ですか

そして適切な措置を講じてください。つまり、チェックサムを変数に入れてからファイル名を入れる必要があります。ファイル名にASCII以外の文字を含めることができますが、改行文字を表示したくありません。次のようになります。

05c00367e8914ca1be0964821d127977  ./.fseventsd/0000000000097aa1
cd9d4291f59a43c0e3d73ff60a337bb5  ./.fseventsd/00000000000fdfec
5d1280769e741e04622cfd852f33a138  ./.fseventsd/0000000000103197
8dda3534e5bbc0be1d15db2809123c50  ./.fseventsd/000000000017c9ca
(...etc., about 100,000 lines)

伝統的には、次のようにすることができます。

md5sum=$(echo $line | awk '{print $1}')
filename=$(echo $line | sed 's/[^ ]*  //')

しかし、これを行うと、どれだけ速くなりますか?

md5sum=${line%%" "*}
filename=${line#*"  "}

答え1

はい、bash内部コマンドを使用すると、多くのシステムコールを回避できます。特に再帰がある場合にはさらにそうです。

別の例:$(ls)に*を使用する必要があります。

Bashは、文字列に対して簡単な操作(切り取りと置換)を実行するためのいくつかの方法を提供します。しかし、それはすべてです。それはそれのために設計されていないからです。例:外部コマンドなしで文字列にパターンがあることを確認するのは難しいです。

外部プログラムはそのタスクに最適化されています(cat、sed、grep、awk、cut、sort...)。

答え2

変数の1つを設定してテストしました。このスクリプトを2回実行します。

while read line; do
        md5sum=${line%%" "*}
        #md5sum=$(echo $line | awk '{print $1}')
        echo "SUM: $md5sum FILE:_$file"
done < manifest.Stuph.180620

まず

md5sum=${line%%" "*}

次は

md5sum=$(echo $line | awk '{print $1}')

"manifest.Stuph.180620"ファイルの長さは100939行(==約14MiB)で、結果は次のようになります。

最初の実行(bashの組み込み文字列操作を使用)

real    0m4.750s
user    0m4.174s
sys     0m0.550s

2回目の実行(パイプを使用)

real    10m54.255s
user    4m42.257s
sys     7m32.880s

私のような一部の人々は、スピードが重要であれば、とにかくシェルでいたずらをするべきではないと言うでしょう。しかし、時には、作業を完了するためにどの環境を使用しても、より効率的であることを望むかもしれません。

これにより、次の点に注意してください。

while read md5sum filename; do
    (...etc...)

変数の割り当てを実行するよりもはるかに効率的ですが、コマンド置換/パイピング/awk設定を削除するポイントではありません。私が最も興味深いのは、bashの組み込みパフォーマンスと外部コマンドの使用の違いです。美しい内蔵機能をさらに一生懸命学び活用します!

関連情報