2012-12-19 12 views
6

Jak mogę wykonać licznik grep za pomocą znacznika czasu?Jak zrobić grep count przy użyciu znacznika czasu?

Przykład: jeśli mam plik, w którym za każdym razem przeszukuję wartość xyz. Plik jest regularnie aktualizowany.

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 

Chcę dowiedzieć się wystąpień xyz po 20121912-08:15:55 która w tym przypadku powinna być 2.

Wykonanie grep -c "xyz" filename czyta cały plik i podaje wynik. Chcę to zrobić po ostatniej aktualizacji lub przy użyciu znacznika czasu.

+3

niefortunny dobór dla formatu timestamp. –

Odpowiedz

1

Jest to rodzaj hack, ale po prostu grep za najwcześniejszą datą chcesz i wydrukować wszystkie linie po tej wykorzystaniem -A a następnie rury grep -c xyz:

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

Uwaga: fgrep jest tylko stałe ciąg grep jak ty "Nie używasz wzorów regex, to jest tak samo jak robisz grep -F.

jako mniej hacky sposób byłoby użyć sed, aby wydrukować wszystkie wiersze z datą, w ten sposób, że nie będzie musiał upewnić się, że wartość -A obejmowałby długość pliku:

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

zakłada to oczywiście plik jest posortowanych według znaczników czasu, jeśli nie jest to wówczas:

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

3 pytania: a, co się stanie, jeśli plik nie zostanie posortowany według datownika? b, a może linia zaczynająca się od 20121912-08: 10: 10? c, a co jeśli istnieje wiele linii po linii 20121912-08? – Kent

+0

Odbierz teraz adresy wszystkich tych punktów. –

2

próbować ten jeden-liner:

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

nie wiedział, że awk będzie analizować i porównywać sygnatury czasowe; bardzo schludny! – Rubens

+0

Daty nie są leksykograficznie malejące, np. 20122011-08: 15: 55 jest "większy" niż 20121912-08: 15: 55. – Thor

+0

czy to działa, a następnie? Myślałem, że awk analizował znaczniki czasu D: – Rubens

1

Możesz powiedzieć sed, aby wydrukował linie z pliku z zakresem (punkt początkowy i końcowy) - zakres może być wyrażeniem regularnym lub liniowym.

Dla potrzeb tego należy zrobić:

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

Tutaj punktem startu jest podawana przez pory traktowane jako wyrażenie regularne i punkt końcowy jest symbolem ostatnia linia $. p mówi sed, aby wydrukować linie w podanym zakresie. Opcja -n sed mówi, aby nie drukować przetwarzanych linii.

0

Hmmm, szybko napisany jeden:

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 

To dość brzydki (nie jestem ani wiersz polecenia sed master) i prawdopodobnie może zostać skrócony, ale jest to sposób, aby to zrobić.Wyjaśnienie poniżej:

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 

Na ostatnim wierszu przykład kroki dałby:

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

Duszponowanie jest w porządku, kiedy wyjaśniono ...? – psycho

1

Czerpiąc inspirację z odpowiedzią Kenta, oto niektóre Perla, który manipuluje dziwne znacznik czasu do RRRRMMDD format:

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

Zakładam, że chcesz znaleźć occu Wzorce wzorca: "xyz", gdzie data/czas jest większa lub równa określonej dacie/godzinie: "20121912-08: 15: 55". Oto, co zrobię przy użyciu GNU awk. Biegać jak:

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

Treść 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)) 
} 

Wyniki:

2 

Alternatywnie, tutaj jest jeden-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 
Powiązane problemy