Tôi có tệp nhật ký 8 Gb (Nhật ký sản xuất Rails). Tôi cần phải cắt nó giữa một số ngày (dòng). Lệnh nào tôi có thể sử dụng để làm điều này?
sed
sẽ làm điều đó một cách dễ dàng.
Tôi có tệp nhật ký 8 Gb (Nhật ký sản xuất Rails). Tôi cần phải cắt nó giữa một số ngày (dòng). Lệnh nào tôi có thể sử dụng để làm điều này?
sed
sẽ làm điều đó một cách dễ dàng.
Câu trả lời:
Cái gì đó như
sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less
tee cut-log
cho phép bạn xem trên màn hình những gì đang được đưa vào tập tin cut-log
.
CHỈNH SỬA:
Để đáp ứng các tiêu chuẩn chính xác của fred.bear, đây là một giải pháp sed (mặc dù có thể nói là giải pháp awk đẹp hơn rất nhiều):
b=BB; e=EE ;echo -e "AA\nAA\nBB\nBB\nCC\nCC\nDD\nDD\nEE\nEE\nFF\nFF" | sed -n ":b;/$b/b p;n;b b;:p;p;n;/$e/b e;b p;:e;p;n;/$e/b e;q"
sed
có thể phù hợp awk
với tốc độ, và nó thực sự nhanh hơn một chút.
Để in mọi thứ giữa FOO và BAR, bao gồm: hãy thử:
$ sed -n '/FOO/,/BAR/p' file.txt
Điều này sẽ làm những gì bạn muốn ...
Cả Bao gồm và Không bao gồm ngày tham số được hiển thị.
# set Test args
set 2011-02-24 2011-02-26 "junk"
from="$1"
till="$2"
file="$3"
# EITHER ==== +++++++++
# Ouptut lines between two parameter dates INCLUDING the parameter dates
awk -v from=$from -v till=$till '
($2 >= from) && ($2 <= till) { print $0 ; next }
($2 > till) { exit }' "$file"
# OR ======== ---------
# Ouptut lines between two parameter dates EXCLUDING the parameter dates
awk -v from=$from -v till=$till '
($2 > from) && ($2 < till) { print $0 ; next }
($2 >= till) { exit }' "$file"
Nó kiểm tra ngày (được sắp xếp) trong trường 2 ... Đây là một ví dụ cho dữ liệu thử nghiệm
98 2011-02-05 xxxx
99 2011-02-05 xxxx
100 2011-02-06 xxxx
101 2011-02-06 xxxx
Và đây là trình tạo dữ liệu thử nghiệm .
awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
if
câu lệnh bổ sung trong tổng số (thậm chí không phải 1 trên mỗi dòng). luồng logic thực sự giống nhau và sự khác biệt về thời gian chạy sẽ được tính bằng nano giây .... Lý do duy nhất tôi không sử dụng "khác" là đây thực sự là awk
kịch bản đầu tiên của tôi (ngoài một ngày 4 năm trước đây khi tôi chơi với một số ví dụ) ... và đó là cơ chế nhánh khả thi đầu tiên tôi tìm thấy ... (và như đã đề cập. Nó cũng nhanh như vậy) .. Tôi thường sử dụng sed
Tryq
Nếu trong tệp nhật ký của bạn, bạn có ngày ở định dạng này YYYY-MM-DD
, thì, để tìm tất cả các mục để nói, 2011 / 02-10, bạn có thể làm:
grep 2011-02-10 log_file
Bây giờ, giả sử, nếu bạn muốn tìm các mục cho 2011/02/10 và 2011/02/11, sau đó, sử dụng grep
lại nhưng với nhiều mẫu:
grep -E '2011-02-10|2011-02-11' log_file
grep
sẽ tìm kiếm toàn bộ tệp, ngay cả khi phạm vi ngày ở đầu tệp. Tính trung bình, điều này làm tăng gấp đôi thời gian tìm kiếm, khi so sánh với "thoát khỏi mục cuối cùng trong phạm vi" ... Tôi chỉ bận tâm đề cập đến điều này vì kích thước tệp 8 GB được đề cập trong câu hỏi, Của bạn kết quả thời gian grep gần giống với ví dụ sed ở đây (1 phút 58 giây). Đây là liên kết đến kết quả kiểm tra thời gian của tôi: paste.ubfox.com/573477
Làm việc với kích thước tập tin này luôn luôn khó khăn.
Một cách chuyển tiếp có thể là chia tệp này thành một vài tệp nhỏ, để làm điều này, bạn có thể sử dụng lệnh split.
split -d -l 50000 ToBigFile.data file_
Ngay cả khi nó được chia ra, bạn vẫn có thể làm việc với tệp như thể là một tệp sử dụng bash for loop
for f in `ls file_*`; do cat $f; done;
Nhưng thay vì con mèo bạn có thể sử dụng grep ngược để loại bỏ dữ liệu không mong muốn, điều đó không liên quan cho việc này. (hoặc loại sàng lọc mà bạn cần).
Tại thời điểm này, bạn sẽ chỉ làm việc với rất nhiều tệp nhỏ hơn và các lệnh mà những người khác được đề cập ở trên sẽ hoạt động mượt mà hơn trên nhiều tệp nhỏ hơn.
Và khi bạn hoàn thành, bạn có thể sử dụng vòng lặp thứ hai để xây dựng lại tệp mới nhỏ hơn.
for f in `ls file_*`; do cat $f >> NewFile.data ; done;
Cập nhật Vì chúng tôi bắt đầu phân chia dữ liệu thành nhiều tệp, sẽ có rất nhiều công việc với ổ cứng và điều đó cần có thời gian. (Trong câu hỏi này rõ ràng là 5 phút).
Mặt khác, các bước tiếp theo có thể sẽ nhanh hơn.
Vì vậy, phương pháp này có thể là vô nghĩa đối với thao tác grep, awk, sed đơn giản, nhưng nếu các mẫu tìm kiếm trở nên phức tạp hơn, nó có thể trở nên nhanh hơn.
perl -wlne '/^2011-02-24/ .. /^2011-02-25/ and print' log_file