2012-12-19 35 views
6

Làm cách nào để có thể thực hiện số đếm grep bằng cách sử dụng dấu thời gian?Làm cách nào để tôi có thể thực hiện một số grep bằng cách sử dụng dấu thời gian

Ví dụ: Nếu tôi có tệp mà tôi tìm kiếm giá trị xyz mọi lúc. Tệp được cập nhật thường xuyên.

20121912-07:15:55 abc cbfr xyz 
20121912-07:16:40 mni cbfr xyz 
----------- 
----------- 
----------- 


20121912-08:15:55 gty cbfr xyz 
20121912-08:20:55 jui uio xyz 

Tôi muốn tìm hiểu các lần xuất hiện của xyz sau 20121912-08:15:55 mà trong trường hợp này nên 2.

Thực hiện grep -c "xyz" filename đọc toàn bộ tệp và đưa ra kết quả. Tôi muốn làm điều đó sau lần cập nhật cuối cùng hoặc sử dụng dấu thời gian.

+3

lựa chọn không may cho định dạng dấu thời gian. –

Trả lời

1

Đây là loại một hack nhưng chỉ grep cho ngày sớm nhất mà bạn muốn và in tất cả các dòng sau đó sử dụng -A và sau đó ống để grep -c xyz:

$ fgrep -A 100 '20121912-08:15:55' file | fgrep -c 'xyz' 
2 

Lưu ý: fgrep chỉ là cố định chuỗi grep như bạn 'không sử dụng mẫu regex, nó giống như làm grep -F.

Như cách ít hacky sẽ được sử dụng sed để in tất cả các dòng từ ngày, bằng cách này bạn sẽ không cần phải chắc chắn rằng các giá trị cho -A sẽ bao gồm chiều dài của file:

$ sed -n '/20121912-08:15:55/,$p' file | fgrep -c 'xyz' 
2 

Điều này giả định tất nhiên bạn nộp là theo thứ tự được sắp xếp bởi timestamps nếu nó không thì:

$ sort file | sed -n '/20121912-08:15:55/,$p' | fgrep -c 'xyz' 
2 
+0

3 câu hỏi: a, điều gì sẽ xảy ra nếu tệp không được sắp xếp theo dấu thời gian? b, làm thế nào về một dòng bắt đầu với 20121912-08: 10: 10? c, nếu có nhiều dòng sau dòng 20121912-08 thì sao? – Kent

+0

Trả lời ngay bây giờ giải quyết tất cả các điểm này. –

2

thử này một liner:

awk '$NF=="xyz"&&$1>="20121912-08:15:55"{x++;}END{print x}' file 
+0

không biết awk sẽ phân tích cú pháp và so sánh dấu thời gian; rất gọn gàng! – Rubens

+0

Ngày không theo thứ tự giảm dần theo thứ tự từ điển, ví dụ: 20122011-08: 15: 55 là "lớn hơn" so với 20121912-08: 15: 55. – Thor

+0

hiện nó có hoạt động không? tôi nghĩ awk đã phân tích cú pháp timestamps D: – Rubens

1

Bạn có thể yêu cầu sed in các dòng từ một tệp được cung cấp một phạm vi (điểm bắt đầu và điểm dừng) - phạm vi có thể là ký hiệu số hoặc dòng số.

Đối với nhu cầu của bạn này nên làm điều đó:

$ sed -n '/20121912-08:15:55/,$p' input.txt | grep -c xyz 

Đây là điểm bắt đầu được đưa ra bởi ngày, coi như một biểu hiện thường xuyên và điểm cuối cùng là dòng cuối cùng biểu tượng $. p yêu cầu sed in các dòng trong phạm vi đã cho. Tùy chọn -n để sed yêu cầu nó không in các dòng mà nó đang xử lý.

0

Hmmm, nhanh chóng viết một:

grep xyz filename | sed -r 's/^([^ ]+).*/ 20121912-08:15:55 <= \1/' | sed -r 's/([0-9]{4})([0-9]{2})([0-9]{2})/\1\3\2/g' | sed 's/[-:]//g' | bc | grep 1 | wc -l 

Nó khá xấu xí (Tôi không phải là một bậc thầy sed hay dòng lệnh) và có lẽ có thể được rút ngắn, nhưng đó là một cách để làm điều đó.Giải thích dưới đây:

grep xyz filename         //gets all interseting lines 
| sed -r 's/^([^ ]+).*/ 20121912-08:15:55 <= \1/' //transform them into 
                 //comparison with the 
                 //date you want 
| sed -r 's/([0-9]{4})([0-9]{2})([0-9]{2})/\1\3\2/g' //invert day and month 
| sed 's/[-:]//g'         //remove separators 
| bc             //ask bc result 
| grep 1            //get true results only 
| wc -l            //and finally count them 

Đối với dòng cuối cùng của ví dụ của bạn, các bước sẽ cung cấp cho:

20121912-08:20:55 jui uio xyz     //grep 'xyz' 
20121912-08:15:55 <= 20121912-08:20:55   //sed 
20121219-08:15:55 <= 20121219-08:20:55   
20121219081555 <= 20121219082055    
1            //result from bc 

HTH

+1

Downvoting là tốt, khi giải thích ...? – psycho

1

Lấy cảm hứng từ câu trả lời của Kent, đây là một số Perl mà thao túng các timestamp lẻ vào YYYYMMDD định dạng:

ts="20121912-08:15:55" patt="xyz" perl -lane ' 
    BEGIN { 
     ($wanted_ts = $ENV{ts}) =~ s/^(....)(..)(..)/$1$3$2/; 
     $pattern = qr{$ENV{patt}}; 
    } 
    ($this_ts = $F[0]) =~ s/^(....)(..)(..)/$1$3$2/; 
    $count++ if $this_ts ge $wanted_ts and /$pattern/; 
    END {print $count} 
' 
1

Tôi giả sử bạn muốn tìm thấy sự kiện rrences của mẫu: 'xyz' trong đó giá trị ngày/thời gian lớn hơn hoặc bằng một ngày/giờ được chỉ định: '20121912-08: 15: 55'. Đây là những gì tôi sẽ làm bằng cách sử dụng GNU awk. Chạy như:

awk -v pattern="xyz" -v time="20121912-08:15:55" -f script.awk file 

Nội dung script.awk:

BEGIN { 
    stamp = convert(time) 
} 

$0 ~ pattern && convert($1) >= stamp { 
    i++ 
} 

END { 
    print i 
} 

function convert(var) { 

    x = "(....)(..)(..)-(..):(..):(..)" 
    y = "\\1 \\3 \\2 \\4 \\5 \\6" 

    return mktime(gensub(x,y,"",var)) 
} 

Kết quả:

2 

Ngoài ra, đây là một trong những-liner:

awk -v pattern="xyz" -v time="20121912-08:15:55" 'BEGIN { stamp = convert(time) } $0 ~ pattern && convert($1) >= stamp { i++ } END { print i } function convert(var) { return mktime(gensub(/(....)(..)(..)-(..):(..):(..)/,"\\1 \\3 \\2 \\4 \\5 \\6","",var)) }' file 
Các vấn đề liên quan