Tôi có tệp văn bản 25 GB cần một chuỗi thay thế chỉ trên một vài dòng. Tôi có thể sử dụng sed
thành công nhưng phải mất một thời gian dài để chạy.
sed -i 's|old text|new text|g' gigantic_file.sql
Có cách nào nhanh hơn để làm điều này?
Tôi có tệp văn bản 25 GB cần một chuỗi thay thế chỉ trên một vài dòng. Tôi có thể sử dụng sed
thành công nhưng phải mất một thời gian dài để chạy.
sed -i 's|old text|new text|g' gigantic_file.sql
Có cách nào nhanh hơn để làm điều này?
Câu trả lời:
Bạn co thể thử:
sed -i '/old text/ s//new text/g' gigantic_file.sql
Từ tài liệu tham khảo này :
Tối ưu hóa cho TỐC ĐỘ: Nếu cần tăng tốc độ thực thi (do các tệp đầu vào lớn hoặc bộ xử lý chậm hoặc đĩa cứng), việc thay thế sẽ được thực hiện nhanh hơn nếu biểu thức "tìm" được chỉ định trước khi đưa ra "s /.../. ../" chỉ dẫn.
Đây là một so sánh trên một tập tin 10G. Trước:
$ time sed -i 's/original/ketan/g' wiki10gb
real 5m14.823s
user 1m42.732s
sys 1m51.123s
Sau:
$ time sed -i '/ketan/ s//original/g' wiki10gb
real 4m33.141s
user 1m20.940s
sys 1m44.451s
sed
là sai chính tả. Tôi đã chỉnh sửa bài đăng này ngày hôm qua để sửa sed
lệnh cuối cùng nên time sed -i '/original/ s//ketan/g' wiki10gb
và không time sed -i '/ketan/ s//original/g' wiki10gb
. Hôm nay tôi hoàn nguyên bản chỉnh sửa của mình vì 1. thời gian không còn khớp lệnh và 2. Tôi đã thực hiện cùng một thử nghiệm với GNU sed trên tệp 3+ GB và tôi không thấy bất kỳ sự khác biệt nào giữa hai sed
lựa chọn thay thế. Tôi nghi ngờ rằng sự khác biệt về thời gian là do lỗi chính tả.
time
kết quả cá nhân, nhưng tất cả, không có sự khác biệt về thời gian.
Câu trả lời ngắn gọn là "Không" - yếu tố giới hạn của bạn đối với loại hoạt động này là đĩa IO. Không có cách nào để truyền phát 25GB đĩa nhanh hơn. Bạn có thể nhận được một cải tiến nhỏ nếu bạn không chỉnh sửa tại chỗ và bạn viết kết quả của sed
một ổ đĩa riêng (nếu bạn có sẵn một ổ đĩa) - bởi vì cách đó bạn có thể đọc từ một, trong khi viết cho một ổ đĩa khác và có một chút Kết quả là ít tranh cãi.
Bạn có thể tăng tốc lên một chút bằng cách không sử dụng công cụ regex cho mỗi dòng - vì vậy, ví dụ như sử dụng perl (tôi khá chắc chắn rằng bạn có thể làm điều này với sed
nhưng tôi không biết cú pháp) - điều này sẽ bắt đầu từ dòng 10.000 trở đi.
perl -pe '$. > 10_000 && s/old_text/new_text/g'
Và nếu có bất kỳ loại phức tạp nào trong RE (siêu nhân vật) thì việc giảm thiểu chúng sẽ giúp cải thiện hiệu quả của công cụ regex một chút .
sed -i '10000,$ s/old_text/new_text/g'
sed
so sánh như thế nào - Tôi giả sử nhanh hơn một chút, nhưng không nhiều vì kích thước tệp.
sed
vào perl
, nhưng sau này cũng cho phép bạn viết nhiều kịch bản dài dòng hơn.
Nếu các văn bản mới và cũ có cùng độ dài, bạn có thể tìm kiếm vào tệp và chỉ viết các byte đã thay đổi, thay vì sao chép toàn bộ tệp. Nếu không, bạn bị mắc kẹt trong việc di chuyển nhiều dữ liệu.
Lưu ý: điều này là khó khăn và liên quan đến việc viết mã tùy chỉnh.
Xem trang hướng dẫn để biết nếu bạn đang làm việc trong C hoặc C ++ hoặc trình bao bọc ngôn ngữ ưa thích của bạn cho các cuộc gọi hệ thống tìm kiếm và viết.
Nếu bạn khăng khăng chỉ sử dụng dòng lệnh và bạn có thể nhận được các byte của văn bản, bạn có thể viết văn bản thay thế tại chỗ bằng các lệnh "dd" được viết cẩn thận.