大容量ファイルの効率的な解析

大容量ファイルの効率的な解析

という名前の数十万のファイルを含むフォルダhp-temps.txt(および多数のサブフォルダ)があります。

そのファイルの内容は次のとおりです。

Sensor   Location              Temp       Threshold
------   --------              ----       ---------
#1        PROCESSOR_ZONE       15C/59F    62C/143F 
#2        CPU#1                10C/50F    73C/163F 
#3        I/O_ZONE             25C/77F    68C/154F 
#4        CPU#2                32C/89F    73C/163F 
#5        POWER_SUPPLY_BAY     9C/48F     55C/131F 

すべてのファイルを解析し、ライン#1で最も高い温度項目を見つける必要があります。

作業中のスクリプトがありますが、時間がかかり、それを改善する方法があるかどうかを知りたいです。

私はシェルスクリプトに初めて触れたので、このコードは本当に非効率的だと思います。

#!/bin/bash
highesetTemp=0
temps=$(find $1 -name hp-temps.txt -exec cat {} + | grep 'PROCESSOR' | cut -c 32-33)
for t in $temps
do
  if [ $t -gt $highestTemp ]; then
    highestTemp=$t
  fi
done

編集する:

非常に効率的なコードがありますが、最大の値しか必要としないことに言及することを忘れていました。

より高い値が検出されたら、ファイルのディレクトリと温度を出力したいので、すべてのファイルを繰り返すことができます。

したがって、出力は次のようになります。

New MAX: 22 in /path/to/file/hp-temps.txt
New MAX: 24 in /another/path/hp-temps.txt
New MAX: 29 in /some/more/path/hp-temps.txt

ベストアンサー1

中間データを文字列として保存するのは遅く、ほとんど必要ありません。通常、単一のスカラー変数に複数の文字列を格納することには、追加の問題があります。このように、各部分文字列にはスペースやその他の文字を含めることができ、後で引用符なしでループ方式を使用してシェルを強制的に解決できます。文字列を分割しますfor(配列を使用する方が良いです)。

この場合、各ファイルを見つけて温度を抽出し、その温度ストリームを読み取る方が効率的です。また、300 KB(またはそれ以上)の文字列を含むシェル変数の生成を防ぎます。

摂氏温度は以下で分析できます。一つファイル使用量

awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3 }' file

2番目のフィールドが文字列の場合、3番目のフィールドの温度を出力しますPROCESSOR_ZONE。書き込み時に3番目のフィールドが整数に変換されるため、値の最初の部分だけが出力されます(数字ではなく最初の部分まで)。

以下から呼び出されますfind

find . -name hp-temps.txt \
    -exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3 }' {} +

これはawk、見つかったファイルの1つ以上のバッチに対してコマンドを実行し、標準出力に順番に温度を出力します。

awk非標準ステートメントを理解することを使用している場合は、nextfileそれを使用してできるだけ早く次のファイルに移動できます。

find . -name hp-temps.txt \
    -exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3; nextfile }' {} +

上記のコマンドで出力された最大値を見つけるには、次のawkコマンドを使用することもできます。

awk 'NR == 1 || $1 > max { max = $1 } END { print max }'

awkmax変数の値がこれまでに確認された最初の値または最大値の場合は、現在の入力値に設定します。最後のmax出力値です。

私はこれがシェルループよりも数倍速いと思います。

総合してみると:

find . -name hp-temps.txt \
    -exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3; nextfile }' {} + |
awk 'NR == 1 || $1 > max { max = $1 } END { print max }'

最大値を持つファイルのファイル名を検索するための追加の要求があります。各ファイルの値とともにファイル名を渡すだけです。では、awk現在の入力ファイルのパス名を特殊変数として使用できますFILENAME

find . -name hp-temps.txt \
    -exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\t%s\n", $3, FILENAME; nextfile }' {} + |
awk 'NR == 1 || $1 > max { max = $1; fname = $2 } END { print max, fname }'

複数のファイルの最大値が等しい場合、見つかった最初のファイルのファイル名が報告されますfind。ユーティリティは、findリストされた順序でファイルを検索します。ls -f

おすすめ記事