Unix grep запрос - PullRequest
       1

Unix grep запрос

1 голос
/ 04 октября 2011
[2011-09-23 18:46:51:697 GMT+00:00][17B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedOut #mouseclicked# userid=1
[2011-09-24 19:46:53:697 GMT+00:00][47B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedOut #mouseclicked# userid=12
[2011-09-25 20:46:51:697 GMT+00:00][57B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedin #mouseclicked# userid=23
[2011-09-25 20:46:51:697 GMT+00:00][57B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] DEBUG mouseclicked by userid=566
[2011-09-25 20:56:56:697 GMT+00:00][77B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedin #mouseclicked# userid=44
[2011-09-26 22:48:55:697 GMT+00:00][87B020C421B4BCC2CEBAD9C1B77CA413.http-8080-6][com.abc.actions.RegisterAction] INFO loggedOut #mouseclicked# userid=55

В приведенном выше файле я хочу знать, сколько раз было # нажатие мыши # за дату в диапазоне с 24 сентября по 25 сентября (включая обе даты).

В вышеприведенном случае команда должна вернуть мне 3 (Примечание: щелчок мышью не считается, так как он не совпадает с #mouseclicked #)

Как я могу использовать команду grep в этом случае?

Ответы [ 3 ]

3 голосов
/ 04 октября 2011

grep само по себе не решит общую проблему. Он не может распознать строки, которые находятся в определенном диапазоне дат. (Ну, это возможно, если вы используете достаточно сложное регулярное выражение, но регулярное выражение будет совершенно разным для каждого интересующего вас диапазона дат.)

Но для вашего конкретного вопроса это будет работать:

egrep -c '^\[2011-09-(24|25).*#mouseclicked#' filename

egrep поддерживает более мощную форму регулярных выражений, включая оператор |. Опция -c говорит ему печатать количество совпадающих строк, а не печатать сами строки.

Но, как вы можете себе представить, если вам нужны строки с 13:00 30 сентября до 11:00 2 октября, регулярное выражение будет намного более сложным, и для его построения потребуется немало значительных усилий.

Если бы я собирался делать это много, я бы написал отдельный инструмент, который извлекает строки из указанного диапазона дат (или дат и времени), используя преимущества конкретного формата даты, используемого в этом файле (ГГГГ -MM-DD HH: MM: SS, ISO-8601, это отличный выбор). Лично я бы написал такой инструмент на Perl. Затем я могу запустить инструмент для файла и передать вывод через grep.

EDIT

В ответ на комментарий grep не понимает диапазоны дат, только последовательности символов. Вы можете написать сложное регулярное выражение, которое будет соответствовать всему в диапазоне с 1 октября 2010 года по 1 декабря 2011 года. Вот моя попытка (не проверенная):

egrep -c '^\[(2010-1.*|2011-(0.|10|11)|2011-12-01).*#mouseclicked#' filename

Это относится к нескольким отдельным поддиапазонам: октябрь-декабрь 2010 года, январь-сентябрь, затем октябрь, затем ноябрь 2011 года и, наконец, 1 декабря 2011 года.

И, как я уже говорил выше, для любого другого диапазона дат (или, что еще хуже, дат и времени) вам нужно будет создать совершенно новое сложное регулярное выражение, которое соответствует поддиапазонам желаемого промежутка времени на основе их текстовое представление, а не их значения как даты.

Вот почему я бы не стал рассматривать такой подход, если бы хотел сделать это более одного или двух раз.

Знаете ли вы язык сценариев, такой как Perl или Python? Если это так, то не составит труда написать сценарий, который на самом деле будет анализировать временные метки и выбирать строки в нужном диапазоне.

На самом деле, я совсем не удивлюсь, если такой инструмент уже существует (я просто не знаю, где его найти).

РЕДАКТИРОВАТЬ 2 :

Вот сценарий Perl, который я создал вместе:

#!/usr/bin/perl

use strict;
use warnings;

die "Usage: $0 start end [file...]\n" if scalar @ARGV < 2;
my $start = shift;
my $end = shift;
$start =~ s/\D//g;
$end   =~ s/\D//g;
$end .= '99999999999999999999999999999';

print "start=\"$start\", end=\"$end\"\n";

while (<>) {
    if (/^\[([^]]+)\]/) {
        my $timestamp = $1;
        $timestamp =~ s/\D//g;
        if ($timestamp ge $start and $timestamp le $end) {
            print;
        }
    }
}

Он обрабатывает указанное время начала и окончания, а также временные метки в файле как последовательности цифр и сравнивает их по строкам (а не числам). Он игнорирует информацию о часовом поясе. Это можно сделать намного более изощренным с помощью одного из модулей времени и даты из CPAN.

На исходный вопрос вы наберете:

this-perl-script 2011-09-24 2011-09-25 input-file | grep -c '#mouseclicked#'
1 голос
/ 05 октября 2011
cat filename | grep '^\[2011-09-2[45]' | grep mouseclicked | wc -l 

Или, проще:

grep '^\[2011-09-2[45]' filename | grep -c mouseclicked
0 голосов
/ 04 октября 2011

Я бы попробовал что-то вроде grep |wc-l

Grep отфильтрует лайки, содержащие вашу строку, а wc -l посчитает количество строк, которые выдаются grep.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...