Làm thế nào để cắt một phần từ tệp nhật ký?


18

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?


1
Chào các bạn, câu hỏi này là về một tập tin lớn , vì vậy đó là "Ante up!" .. vấn đề thời gian ... Tôi đã thử nghiệm tập lệnh sed ưa thích trên một tập tin 8 GB thực sự, với 85904064 dòng (100 ký tự trên mỗi dòng). Tôi yêu sed, nhưng khi nó đứng, kịch bản sed quét toàn bộ tập tin, mọi lúc. Điều này làm cho nó trung bình chậm gấp đôi so với tập lệnh awk xuất hiện khi tôi tìm thấy ... Tôi nghĩ (?) Tập lệnh sed có thể chỉ cần aq thay vì d cho biểu thức thứ hai ... Kết quả kiểm tra có ở đây: dán .ubfox.com / 573477 .. Ngoài ra, nó không tạo ra đầu ra thích hợp .. xem nhận xét của tôi ở cuối câu trả lời của asoundmove.
Peter.O

Phiên bản sed mới của asoundmove đã giải quyết vấn đề tốc độ, và giờ đây nó phù hợp với tốc độ của awks. và phiên bản mới hiện xuất dữ liệu chính xác ... xem bình luận của anh ấy để biết thêm chi tiết.
Peter.O

Tôi chỉ nhận thấy bạn nói "cắt" (thường có nghĩa là loại bỏ) ... Bạn thực sự có nghĩa là "cắt", hay bạn có nghĩa là "sao chép"? .... Nếu bạn có nghĩa là "cắt", sau đó sedsẽ làm điều đó một cách dễ dàng.
Peter.O

Câu trả lời:


12

Cái gì đó như

sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less

tee cut-logcho 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"


3
@dogbane: vâng, vâng. Đã chỉnh sửa. Tôi chắc chắn rằng đôi khi bạn viết ít hơn mã tối ưu, nó có xứng đáng nhận được một nhận xét khắc nghiệt như vậy không?
asoundmove

1
lưu ý: Nếu có nhiều dòng 'ngày đầu tiên' liên tiếp có cùng ngày, tất cả ngoại trừ dòng đầu tiên sẽ không bị xóa và sẽ được đưa vào đầu ra ... chỉ cần một cái gì đó để nhận biết ... (điều này phụ thuộc vào tình hình)
Peter.O

1
... nhưng, mặc dù tôi là một pro-sed ++, tôi nghĩ công việc đặc biệt này vượt quá giới hạn của nó, đối với bất kỳ thứ gì khác ngoài công cụ cá nhân của riêng mình .. Đây là vấn đề chính mà sed có trong trường hợp này (của bạn, và của tôi .. Tôi đã quản lý để có được sed để làm giống như của bạn .. nó cũng chạy trong vòng 1%) .. trở lại vấn đề chính .. (không áp dụng cho awk) .... Lỗi (không thể sửa chữa): Về ngày có giá trị trong phạm vi nhật ký, nhưng thực tế không có trong nhật ký, trong trường hợp của đối số thứ nhất, sẽ khiến sed không in được gì, và trong trường hợp của lần thứ 2, sed sẽ in mọi thứ sau buổi hẹn hò đầu tiên! ... thêm ...
Peter.O

1
Một lỗi khác, có thể sửa được: Có phải nó hiện đang khớp với bất kỳ ngày nào trong bất kỳ dòng nào, bao gồm cả dữ liệu, nhưng đó chỉ là một chỉnh sửa regex .. Và đối với bất kỳ ai muốn sử dụng nó, có lẽ bạn có thể nhận xét rằng các đối số bây giờ đề cập đến đầu tiên và ngày cuối cùng trong phạm vi (không phải -1 và +1) .. và cuối cùng .. "tiêu chuẩn chính xác" của tôi không phải là của tôi. Tôi chỉ là người đưa ra yêu cầu của Người hỏi ... Người dùng sẽ nhận thấy liệu nó có hoạt động như yêu cầu hay không .. Đây là một câu hỏi tuyệt vời đối với tôi .. Tôi đã học được rất nhiều :) ... và tôi rất vui để biết rằng sedcó thể phù hợp awkvới tốc độ, và nó thực sự nhanh hơn một chút.
Peter.O

6

Để in mọi thứ giữa FOO và BAR, bao gồm: hãy thử:

$ sed -n '/FOO/,/BAR/p' file.txt

1
lưu ý: Điều này sẽ chỉ in BAR đầu tiên của một loạt các BARS liên tiếp ...
Peter.O

một lưu ý khác ... Vấn đề lớn nếu một trong hai ngày không xuất hiện trong dữ liệu .. Nếu ngày cuối cùng không có mặt, sed sẽ tiếp tục xuất các dòng cho đến khi đạt đến EOF.
Peter.O

5

Đ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 .


Tôi sẽ viết nó (lấy ví dụ đầu tiên) ví dụ đơn giản hơn một chút: awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
asoundmove

@asoundmove: Vâng, điều đó có thể trông tốt hơn và chắc chắn là thông thường hơn , nhưng trong thực tế, thời gian thực hiện của nó chỉ là thời lượng của 1 ifcâ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à awkkị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 sedTryq
Peter.O

Tôi không hiểu nơi bạn cung cấp tên và vị trí tệp văn bản trong phương pháp này? ai đó có thể giúp tôi nhìn thấu sự ngu ngốc của mình không
Giles

4

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 greplại nhưng với nhiều mẫu:

grep -E '2011-02-10|2011-02-11' log_file

Tốt Nó hoạt động "như quảng cáo" :) ... Tuy nhiên, grepsẽ 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
Peter.O

1

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.


3
Johanm, trung bình chỉ mất 1 phút và để tìm kiếm tệp nhật ký 8 GB trên máy tính của tôi và trên cùng một trình biên dịch, chỉ cần tách tệp bẩm sinh, mất 4 phút 43 giây ... :)
Peter.O

Giả sử bạn có thể cắt giảm 50% thời gian awk và sed trên các tệp nhỏ hơn. Sau đó, chúng tôi vẫn cần thực hiện hơn 10 thao tác đó trước khi chúng tôi đạt được tổng thời gian ... Vì vậy, có thể phân tách tệp không phải là ý tưởng tốt nhất cho một vài hồi quy ...
Johan

Tập lệnh awk có thể (dễ dàng) được sửa đổi để xuất 10 kết quả tìm kiếm khác nhau thành 10 tệp..trong một lần duy nhất, nhưng điều đó sẽ làm chậm việc đọc trong khi thực sự xuất báo cáo ... Sed cũng có thể làm như vậy, nhưng như tôi Tôi đã đề cập trong các bình luận của asoundmove, sed sẽ thất bại nếu một ngày / giờ cụ thể không có mục nào trong nhật ký (ví dụ: bạn đang tìm kiếm theo giờ) .. Tôi sử dụng sed rất nhiều và nó cực kỳ hữu ích, nhưng nó có giới hạn của nó ... Đây là một câu hỏi thường gặp về sed khi nào nên sử dụng sed vs awk .. Tôi không nhất thiết phải đồng ý với tất cả, nhưng tôi có thể thấy ý nghĩa của chúng ... sed.sourceforge.net/sedfaq6.html
Peter. O

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.