grep의 과도한 불필요한 메모리 사용을 방지하는 방법

grep의 과도한 불필요한 메모리 사용을 방지하는 방법

대용량 바이너리 파일(1TB)에서 16진수 패턴(현재 숫자)을 수집하고 있습니다.

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

최대 7GB의 RAM을 사용하고 더 이상 RAM을 사용할 수 없다는 오류 메시지와 함께 작동이 중단되는 이유가 궁금합니다 grep(RAM(16GB + 8GB 스왑)이 더 많지만 메시지가 표시됨). 내 질문은

  • grep아무것도 기억할 필요가 없는데 왜 그렇게 많은 메모리를 사용합니까?(검색 결과는 즉시 stdout으로 인쇄됩니다(출력이 없으므로 검색 결과가 없다고 가정하고 작은 파일에서는 검색 결과가 즉시 표시됩니다).
  • 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그것이 존재하는지 확인하려면 개행 문자를 제거해야 합니다(그렇지 않으면 문자열이 두 줄에 걸쳐 있을 수 있음). .

다음 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각 줄의 데이터는 여전히 두 번(한 번은 이전 줄에 한 번, 다음 줄에 한 번).

관련 정보