정렬 된 파일을 효율적으로 검색


12

각 줄에 하나의 문자열을 포함하는 큰 파일이 있습니다. 문자열이 파일에 있는지 빠르게 확인할 수 있기를 원합니다. 이상적으로는 이진 절단 유형 알고리즘을 사용하여 수행됩니다.

일부 인터넷 검색 은 이진 검색 알고리즘을 사용하여 주어진 접두사로 시작하는 모든 문자열을 찾아 출력 할 것을 약속 look하는 -b플래그로 명령을 공개했습니다 . 불행히도 올바르게 작동하지 않는 것 같고 파일에있는 문자열에 대해 null 결과를 반환합니다 (동등한 grep검색에 의해 올바르게 반환됩니다 ).

누구나이 파일을 효율적으로 검색하는 다른 유틸리티 또는 전략을 알고 있습니까?


상단 답변은 잘못된 정렬을 나타냅니다 : 사실 정렬해야합니다 : LC_COLLATE = C sort -d look명령이 올바르게 작동하려면 로케일을 무시하고 하드 코딩 된 정렬과 같은 C를 사용하기 때문에 버그를 열었습니다. 이 혼란스러운 행동으로 인해 : bugzilla.kernel.org/show_bug.cgi?id=198011
Sur3

look -b오류로 인해 실패했습니다 File too large. 모든 것을 메모리로 읽으려고한다고 생각합니다.
Brian Minton

답변:


9

grep와 사이에는 근본적인 차이점이 있습니다 look.

달리 명시되지 않는 한 grep, 라인 어딘가에서 패턴을 찾을 수 있습니다. 대한 look맨 페이지 상태 :

look — 주어진 문자열로 시작 하는 행을 표시 합니다

나는 look자주 사용 하지 않지만 방금 시도한 사소한 예에서는 잘 작동했습니다.


1
검색 해야하는 파일에는 약 110,000,000 줄이 있습니다. 내가 할 경우 egrep "^TEST" sortedlist.txt | wc -l 내가 41,289 결과를 얻을 수 있습니다. 그러나 동등한 look명령 look -b TEST sortedlist.txt | wc -l은 1995 개의 결과 만 산출합니다. 에 버그가 있는지 궁금합니다 look.
Matt

1
@Matt 아마도 look파일을 정렬하는 데 사용한 프로그램과 다른 데이터 정렬 설정을 사용하고있을 것입니다.
kasperd

4

아마 약간 늦게 대답 :

그렙은 당신을 도울 것입니다.

Sgrep (정렬 grep)은 정렬 된 입력 파일에서 검색 키와 일치하는 행을 검색하고 일치하는 행을 출력합니다. 큰 파일을 검색 할 때 sgrep은 기존 Unix grep보다 훨씬 빠르지 만 상당한 제한이 있습니다.

  • 모든 입력 파일은 일반 파일로 정렬되어야합니다.
  • 정렬 키는 줄의 시작 부분에서 시작해야합니다.
  • 검색 키는 줄의 시작 부분에서만 일치합니다.
  • 정규식 지원이 없습니다.

https://sourceforge.net/projects/sgrep/?source=typ_redirect에서 소스를 다운로드 할 수 있습니다.

그리고 여기에있는 문서 : http://sgrep.sourceforge.net/

또 다른 방법:

파일이 얼마나 큰지 모르겠습니다. 병렬을 시도해야 할 수도 있습니다.

/programming/9066609/fastest-possible-grep

항상 100GB보다 큰 파일로 grep을 수행하면 제대로 작동합니다.



네, 다운로드 링크를 작성합니다 ...
memorybox

그게 다라면 새 답변을 게시하는 대신 게시물을 수정 해야합니다 .
muru

그 게시물 추천 : sudo apt-get install sgrep sgrep를 얻으려면, buntu 저장소의 sgrep은 실제로이 sgrep이 아닙니다. 나는 그것이 똑같은지 확실하지 않습니다.
memorybox

0

파일을 조각으로 해시 한 다음 원하는 조각을 grep 할 수 있습니다.

for line in $(cat /usr/share/dict/american-english | tr '[:upper:]' '[:lower:]' | sort | uniq)
do
    prefix=$(echo $line | md5sum - | cut -c 1-2)
    mkdir -p $prefix
    echo $line | gzip >> $prefix/subwords
done

조회는 다음과 같습니다.

    prefix=$(echo $word | md5sum - | cut -c 1-2)
    zgrep -m 1 -w word $prefix/subwords

이것은 두 가지 일을합니다.

  1. 압축 파일을 읽고 씁니다. 일반적으로 디스크 대신 CPU에 부하를 가하는 것이 더 빠릅니다 (매우 느림).
  2. 대략 동일한 분포를 얻기 위해 해시를 사용하려면 각 조각의 크기를 줄이기 위해 원하는대로 짧거나 긴 해시를 사용할 수 있습니다 (그러나 중첩 된 하위 디렉토리를 사용하는 것이 좋습니다)

0

sgrep 이 당신을 위해 일할 수 있습니다 :

sudo apt-get install sgrep
sgrep -l '"needle"' haystack.txt

프로젝트 페이지 http://sgrep.sourceforge.net/ 는 다음과 같이 말합니다.

Sgrep은 이진 검색 알고리즘을 사용하는데 매우 빠르지 만 정렬 된 입력이 필요합니다.

그러나 삽입을 위해 데이터베이스를 사용하는 것보다 더 나은 해결책은 없다고 생각합니다. /programming/10658380/shell-one-liner-to-add-a-line-to-a-sorted-file/ # 33859372


3
sgrep우분투 저장소에서이 실제로 이의 sgrep "구조화 된 패턴 파일을 검색"설계와 이진 검색과는 아무 상관이 없습니다.
ingomueller.net

0

정말로 빠르기 를 원한다면 (O (1) 빠름) 해시 세트를 만들어 살펴볼 수 있습니다. 사전 빌드 해시 세트를 파일에 저장하고 전체 파일을 메모리로 읽을 필요없이 파일을 검사 할 수있는 구현을 찾을 수 없으므로 내 롤백했습니다 .

해시 세트 ( -b/ --build)를 빌드하십시오 .

./hashset.py --build string-list.txt strings.pyhashset

해시 세트 프로브 ( -p/ --probe) :

./hashset.py --probe strings.pyhashset \
    'Is this string in my string list?' 'What about this one?'

… 또는 표준 입력에서 조회 할 문자열이있는 경우 :

printf '%s\n' 'Is this string in my string list?' 'What about this one?' |
./hashset.py --probe strings.pyhashset

종료 상태에만 관심이있는 경우 / 옵션 을 --probe사용 하여 출력을 끌 수 있습니다.-q--quiet

if ./hashset.py --quiet --probe strings.pyhashset ...; then
    echo 'Found'
else
    echo 'Not found'
fi

자세한 옵션은 -h/ --help옵션 또는 함께 제공되는 README파일을 통해 액세스 할 수있는 사용법 설명을 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.