대용량 바이너리 파일(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
각 줄의 데이터는 여전히 두 번(한 번은 이전 줄에 한 번, 다음 줄에 한 번).