Многострочная группа и поиск с помощью Regex - PullRequest
2 голосов
/ 30 сентября 2008

Хорошо, волшебники Regex. Я хочу иметь возможность искать в моем файле журнала и находить любые сеансы со словом «ошибка» в нем, а затем возвращать всю запись журнала сеанса.

Я знаю, что могу сделать это с помощью строки / массива, но я бы хотел узнать, как это сделать с помощью Regex, но вот вопрос. Если я решу сделать это с Regex, у меня будет одна или две проблемы ? ; О)

Вот лог:

PS: я использую движок Perl Regex.

Примечание : Я не думаю, что смогу сделать это в Regex. Другими словами, у меня сейчас две проблемы. ; о) Я попробовал решения ниже, но, поскольку я запутал проблему, заявив, что я использую движок Perl, многие ответы были на Perl (который не может быть использован в моем случае). Однако я опубликовал свое решение ниже.


2008.08.27 08:04:21 (Wed)------------Start of Session-----------------  
Blat v2.6.2 w/GSS encryption (build : Feb 25 2007 12:06:19)  
Sending stdin.txt to foo@bar.com  
Subject: test 1  
Login name is foo@bar.com  
The SMTP server does not require AUTH LOGIN.  
Are you sure server supports AUTH?  
The SMTP server does not like the sender name.  
Have you set your mail address correctly?  
2008.08.27 08:04:24 (Wed)-------------End of Session------------------  

2008.08.27 08:05:56 (Wed)------------Start of Session-----------------  
Blat v2.6.2 w/GSS encryption (build : Feb 25 2007 12:06:19)  
Error: Wait a bit (possible timeout).  
SMTP server error  
Error: Not a socket.  
Error: Not a socket.  
2008.08.27 08:06:26 (Wed)-------------End of Session------------------  

2008.08.27 08:07:58 (Wed)------------Start of Session-----------------  
Blat v2.6.2 w/GSS encryption (build : Feb 25 2007 12:06:19)  
Sending stdin.txt to foo@bar.com  
Subject: Lorem Update 08/27/2008  
Login name is foo@bar.com  
2008.08.27 08:07:58 (Wed)-------------End of Session------------------  

Ответы [ 8 ]

7 голосов
/ 01 октября 2008

Ответ Кайла, вероятно, самый прелюбодейный, но если у вас есть все в одной строке и вы хотите использовать одно регулярное выражение, вот (проверенное) решение:

( Второе обновление : немного исправлено, теперь более читабельно, чем когда-либо; -)

my $re = qr{
        (           # capture in $1
         (?:
          (?!\n\n). # Any character that's not at a paragraph break
         )*        # repeated
         error
         (?:
          (?!\n\n).
         )*
        )
}msxi;


while ($s =~ m/$re/g){
    print "'$1'\n";
}

Ужасно, но ты просил об этом.

6 голосов
/ 01 октября 2008

Похоже, что ваши сеансы разделены пустыми строками (в дополнение к маркерам начала / конца). Если это так, то это один вкладыш:

perl -ne 'BEGIN{$/=""} print if /error/i' < logfile

1 голос
/ 01 октября 2008
/(?:[^\n\r]|\r?\n(?!\r|\n))*?Error:(?:[^\n\r]|\r?\n(?!\r|\n))*/g

При этом используются пустые строки между записями. Это работает как для Unix, так и для разрывов строк Windows. Вы можете заменить текст «Ошибка:» посередине почти на что угодно, если хотите.

0 голосов
/ 24 октября 2008

Время от времени, когда был доступен только Vim (и sed, awk, который я тогда не освоил), я делал что-то вроде:

Через vim я соединил все строки между - в вашем случае - началом сеанса / концом сеанса в одной строке:

  • Сначала заменил все окончания строки на какой-то определенный символ

    :% s: $ #

  • Затем двойник входит в какой-то другой разделитель:

    :% S: # \ п # \ п # \ г @ \ г

  • Объединение строк:

    :% S: # \ п #

  • Отображаются только строки с ошибкой:

    : v / [Ee] rror / d

  • Разделить строки в исходном формате:

    :% S: #: \ г

НТН

0 голосов
/ 02 октября 2008

То, что я сделал, - запустил весь журнал в строку, затем прошел по строке и добавил каждую строку к третьей переменной, пока строка не содержала «- Конец сеанса--». Затем я добавил эту строку в 3-й вариант и затем поискал в 3-м элементе слово «ошибка». Если он содержал его, я добавил 3-й вар к четвертому, а затем очистил 3-й вар и начал возвращаться к вар с журналом на следующей строке.

Это выглядит так:

str a b email gp lgf
lgf.getfile( "C:\blat\log.txt")
foreach a lgf
    if(find(a "--End of Session--")>-1)
        gp.from(gp "[]" a)
        if(find(gp "error" 0 1)>-1)
            gp.trim
            email.from(email gp "[]")
        gp=""
        continue
    gp.from(gp "[]" a)
email.trim

Оказывается, что регулярное выражение действительно может быть «медвежьим котом», если оно плохо подходит. Вроде как использовать отвертку вместо молотка. Это выполнит работу, но займет много времени, сломает отвертку и, вероятно, повредит вам в процессе.

0 голосов
/ 02 октября 2008

Если вы хотите понять или поиграть с любым из этих решений, я настоятельно рекомендую загрузить Regex Coach , который поможет вам создавать и тестировать регулярные выражения

0 голосов
/ 01 октября 2008

С двигателем регулярного выражения Perl, простое регулярное выражение

Error:.+ 

выполняет трюк согласно quickrex .

(При использовании движка Java для регулярных выражений потребовалось бы другое регулярное выражение:

(?ms)^Error:[^\r\n]+$

)

регулярное выражение с группой захвата позволит перенаправить только сообщение об ошибке, а не само сообщение об ошибке, как в:

Error:\s*(\S.+)

Группа № 1 захватывает только то, что следует за «Ошибка:»

Как бы то ни было, для того, чтобы узнать о правилах, см. регулярное руководство по Express-Expressions.info , первоклассное введение в эту технику.

0 голосов
/ 01 октября 2008

Как сказал последний парень, Perl из командной строки будет работать. Так будет awk из командной строки:
awk '/-Start of Session-/ { text=""; gotError=0; } /Error/{gotError=1;}/-End of Session-/{ if(gotError) {print text}} { text=text "\n" $0}' logFileName.txt

По сути, начать запись в строке с «-Start of Session-», установить флаг в строке с «Error» и условно вывести в строку с «-End of Session -».

Или поместите это в errorLogParser.awk:

/-Start of Session-/{
    text="";
    gotError=0;
}
/Error/{
    gotError=1;
}
/-End of Session-/{
    if(gotError)
    {
        print text
    }
}
{
    text=text "\n" $0
}
... и вызывать так: awk -f errorLineParser.awk logFileName.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...