GNU 병렬 처리가 없는 대규모 파일 세트의 grep 패턴

GNU 병렬 처리가 없는 대규모 파일 세트의 grep 패턴

36 코어 시스템에서 10M 파일의 패턴을 빠르게 찾고 싶습니다. 이것을 시도했습니다.

find . -name '*.xml' -type f | xargs  -P 20 grep "username" >> output

하지만 그 사이에 다른 결과도 얻었습니다.

이를 수행하는 더 좋은 방법이 있습니까?

미리 감사드립니다.

답변1

데이터가 RAID가 아닌 HDD에 있다는 점을 고려하면 병렬화를 통해 더 나은 성능을 얻을 수 있을지 의문입니다. 병목 현상은 CPU가 아닌 I/O일 가능성이 높습니다.

LC_ALL=C grep -rwF --include='*.xml' username . > /on/some/other/disk/output

아마도 당신이 얻을 수 있는 최고에 가깝습니다.

병렬화하려면 다음을 수행해야 합니다.

LC_ALL=C find . -name '*.xml' -type f -print0 |
  LC_ALL=C xargs -r0P20 -n 1000 grep -HFw --line-buffered username > output

4KiB보다 긴 출력 라인(입력 라인 + 파일 경로 이름)이 없다고 가정하고, 20개의 동시 grep 라인이 결국 인터리브된다는 점에 유의하세요.

바라보다:

더 알아보기.

답변2

패턴이 너무 일반적이어서 그런 것 같아요. 일반적으로 명령줄 유틸리티는 stderr 또는 터미널에 오류를 인쇄합니다. 출력 파일에 들어가서는 안 됩니다.

답변3

이런 방식으로 파일을 grepping 하면 xml검색 문자열이 포함된 전체 줄이 반환되거나, xml파일에 개행 문자가 없으면 전체 파일 내용이 반환됩니다. 10M 파일에는 "기타"가 상당히 많습니다.

xml@Kusalananda의 의견에 따르면, 더 나은 도구를 사용하여 파서를 강제로 사용하는 것은 grep좋은 습관이 아니지만 , 주장한다면...xmlxmllint

반환 값을 제한하는 옵션을 확인하고 읽고 man이를 사용하여 찾고 있는 일치 항목의 전체 길이를 정의하십시오.grep-oregex

username속성인 경우

grep -o 'username="[^"]*"'

또는 더 나은

xmllint --xpath "//@username"

노드 라면 username다음과 비슷하다.

grep -o "username>[^<][^<]*"

또는 더 나은

xmllint --xpath "//username"

모든 xmllint쿼리에 대해 쿼리를 래핑하여 string()속성이나 노드 텍스트를 추출하면 됩니다.

xmllint --xpath "string(//username)"
xmllint --xpath "string(//@username)"

관련 정보