Tìm kiếm hiệu quả tập tin được sắp xếp


12

Tôi có một tệp lớn chứa một chuỗi trên mỗi dòng. Tôi muốn có thể nhanh chóng xác định nếu một chuỗi trong tập tin. Lý tưởng nhất, điều này sẽ được thực hiện bằng cách sử dụng thuật toán loại nhị phân.

Một số Googling đã tiết lộ looklệnh với -bcờ hứa hẹn sẽ xác định vị trí và xuất tất cả các chuỗi bắt đầu bằng một tiền tố nhất định bằng thuật toán tìm kiếm nhị phân. Thật không may, nó dường như không hoạt động chính xác và trả về kết quả null cho các chuỗi mà tôi biết có trong tệp (chúng được trả về đúng bởi greptìm kiếm tương đương ).

Có ai biết về một tiện ích hoặc chiến lược khác để tìm kiếm tập tin này một cách hiệu quả không?


Câu trả lời trên cùng cho biết cách sắp xếp sai: thực tế là bạn phải sắp xếp với: LC_COLLATE = C sort -d để looklệnh hoạt động chính xác, vì có vẻ như bỏ qua miền địa phương và chỉ sử dụng C như sắp xếp mã hóa cứng, tôi cũng đã mở một lỗi vì hành vi khó hiểu này: bugzilla.kernel.org/show_orms.cgi?id=198011
Sur3

look -bthất bại với tôi với một lỗi File too large. Tôi nghĩ rằng nó đang cố đọc toàn bộ vào bộ nhớ.
Brian Minton

Câu trả lời:


9

Có một sự khác biệt thiết yếu giữa greplook:

Trừ khi có quy định rõ ràng khác, grepsẽ tìm thấy các mẫu ngay cả ở đâu đó trong các dòng. Đối với lookcác trang man trạng thái:

nhìn - hiển thị các dòng bắt đầu bằng một chuỗi nhất định

Tôi không sử dụng lookrất thường xuyên, nhưng nó đã hoạt động tốt trên một ví dụ tầm thường mà tôi vừa thử.


1
Các tập tin tôi cần tìm kiếm có khoảng 110.000.000 dòng. Nếu tôi làm egrep "^TEST" sortedlist.txt | wc -l tôi nhận được 41.289 kết quả. Tuy nhiên, các looklệnh tương đương , look -b TEST sortedlist.txt | wc -lchỉ mang lại kết quả 1995. Tôi gần như tự hỏi nếu có một lỗi trong look.
Matt

1
@Matt Có thể lookđang sử dụng các cài đặt đối chiếu khác với chương trình bạn đã sử dụng để sắp xếp tệp.
kasperd

4

Có lẽ hơi muộn trả lời:

Sgrep sẽ giúp bạn.

Sgrep (grep được sắp xếp) tìm kiếm các tệp đầu vào được sắp xếp cho các dòng khớp với khóa tìm kiếm và xuất ra các dòng khớp. Khi tìm kiếm các tệp lớn, sgrep nhanh hơn nhiều so với grep Unix truyền thống, nhưng với các hạn chế đáng kể.

  • Tất cả các tập tin đầu vào phải được sắp xếp các tập tin thường xuyên.
  • Khóa sắp xếp phải bắt đầu ở đầu dòng.
  • Khóa tìm kiếm chỉ khớp ở đầu dòng.
  • Không hỗ trợ biểu thức chính quy.

Bạn có thể tải nguồn tại đây: https://sourceforge.net/projects/sgrep/?source=typ_redirect

và các tài liệu ở đây: http://sgrep.sourceforge.net/

Cách khác:

Tôi không biết tệp lớn đến mức nào. Có thể bạn nên thử song song:

/programming/9066609/festest-possible-grep

Tôi luôn luôn thực hiện grep với các tệp có kích thước> 100GB, nó hoạt động tốt.


2
Đó không phải là đã có trong Askubfox.com/a/701237/158442 ?
muru

vâng, tôi điền vào liên kết tải xuống ...
hộp nhớ

Nếu đó là tất cả, bạn nên chỉnh sửa bài đăng đó thay vì đăng một câu trả lời mới.
muru

bài đăng đó được đề xuất: sudo apt-get install sgrep để có được sgrep, sgrep trong kho lưu trữ buntu không thực sự là sgrep này, tôi không chắc đó là điều tương tự.
hộp nhớ

0

Bạn có thể băm tập tin thành từng mảnh và sau đó grep chỉ phần bạn muốn:

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

sau đó tra cứu sẽ như thế nào:

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

Điều này có hai điều:

  1. đọc và ghi các tập tin nén. Nói chung là nhanh hơn để đặt tải lên cpu (rất nhanh) thay vì đĩa (rất chậm)
  2. băm những thứ để có được phân phối xấp xỉ bằng nhau, bạn có thể sử dụng hàm băm ngắn hơn hoặc dài hơn như bạn muốn để giảm kích thước của mỗi phần (nhưng tôi khuyên bạn nên sử dụng các thư mục con lồng nhau nếu bạn làm như vậy)

0

sgrep có thể làm việc cho bạn:

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

Trang dự án http://sgrep.sourceforge.net/ nói:

Sgrep sử dụng thuật toán tìm kiếm nhị phân, rất nhanh, nhưng yêu cầu đầu vào được sắp xếp.

Tuy nhiên, để chèn, tôi nghĩ không có giải pháp nào tốt hơn là sử dụng cơ sở dữ liệu: /programming/10658380/shell-one-liner-to-add-a-line-to-a-sortic-file/ 33859372 # 33859372


3
Các sgrepkho lưu trữ trong Ubuntu thực sự là sgrep này , được thiết kế để "tìm kiếm một tệp cho một mẫu có cấu trúc" và không liên quan gì đến tìm kiếm nhị phân.
ingomueller.net

0

Nếu bạn muốn nó thực sự nhanh (O (1) nhanh), bạn có thể xây dựng một bộ băm để xem xét. Tôi không thể tìm thấy một triển khai cho phép tôi lưu trữ một hàm băm dựng sẵn trong một tệp và thăm dò nó mà không cần phải đọc toàn bộ tệp vào bộ nhớ, vì vậy tôi tự cuộn .

Xây dựng bộ băm ( -b/ --build):

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

Thăm dò bộ băm ( -p/ --probe):

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

Có thể có chuỗi để tra cứu đầu vào tiêu chuẩn:

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

Bạn có thể yên tĩnh đầu ra của --probevới -q/ --quiettùy chọn nếu bạn chỉ quan tâm đến trạng thái thoát:

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

Để biết thêm tùy chọn, hãy xem mô tả sử dụng có thể truy cập thông qua tùy chọn -h/ --helphoặc READMEtệp đi kèm .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.