grepの過剰な不要なメモリ使用を防ぐ方法

grepの過剰な不要なメモリ使用を防ぐ方法

大容量バイナリファイル(1TB)から16進パターン(現在の数字)を収集しています。

xxd -p /path/to/sda.img | tr -d '\n' | grep -ob '117a0cb17ada1002'

最大7 GBのRAMを使用し、RAMが使用できなくなるというエラーメッセージで動作が停止する理由があると思いますgrep(RAM(16GB + 8GBのスワップ)が多いがメッセージが表示されます)。私の質問は

  • grep何も覚えておく必要はありませんが、なぜそれほど多くのメモリを使用しますか?
  • grep同じ操作を実行するために代替コマンドセットを使用せずにこれらのメモリを使用しないようにするにはどうすればよいですか?

\n正しいバイトオフセットを得るために削除しました。多くの計算を行わずに(挿入された改行数の減算など)、区切り文字なしでファイル/行の位置を知りたいです。

grep私はUbuntu 14.10 amd64で2.20-3を実行しています。

答え1

grep行単位の一致によりメモリが不足し、パイプからすべての改行を明示的に削除しました。

$ xxd -p /path/to/sda.img | tr -d '\n' | grep -ob '117a0cb17ada1002'

私はあなたが望むものが出力の特定の16進文字列のバイトオフセットを見つけることを前提としており、xxdそれが存在することを確認するには改行文字を削除する必要があります(そうでない場合は、文字列が2行にわたっている可能性があります)。 。

次のawkスクリプトは、連続した行のパターンを一致させ、端末に一致する最初の文字の位置を印刷します。入力の幅が正確に60文字であるとします(isの出力と同じxxd -p)。

{
    if (NR > 1 && offset = match(line $0, pattern)) {
        printf("%d: %s\n", (NR - 2)*60 + offset, pattern);
    }

    line = $0;
}

または代替として(しかし等しく):

NR > 1 {
    if (offset = match(line $0, pattern)) {
        printf("%d: %s\n", (NR - 2)*60 + offset, pattern);
    }
}

{ line = $0 }

ランダム入力データに対してテストします(使用中の検索文字列がデータ内で強調表示されます)。

$ xxd -p ランダム.dat ヘッダー -n 5 |
b1a632f5218b1404d9873dc20ae80e687c99c618bfc0f92db007c36c2888
21a99d23914e34510b9ab8e1c2b340cf1e4a0585b788aecbbc64f01a7a52
62e1746ca1fa4ff65d575419522d52169c5d3f9eee0e204979d79634db9b
fa78320eb7b9e072adc53720785fc7b65a1ffb04cc77566686ea7400fe交換
f32afc1539690d0046bc13706404d82112442d4bc447ac95df1fe96cd4bd
$ xxd -p random.dat | awk -v pattern=b1a632f5 -f script.awk
1: b1a632f5

$ xxd -p random.dat | awk -v pattern=288821a9 -f script.awk
57: 288821a9

$ xxd -p random.dat | awk -v pattern=ac00fef3 -f script.awk
235: ac00fef3

とにかく大容量の1TBファイルで実行すると速度が遅くなります。パターン一致の数を減らすための-c 256オプションを提供xxdし、それに応じてスクリプトで60を256に変更して速度を上げることができますが、各行awkのデータはまだ2回(一度は前の行に1回、次の行に1回)。

関連情報