2016-07-19 4 views
1

У меня есть две строки журнала, где я хочу иметь отдельное регулярное выражение для поиска каждого из них. Во второй строке журнала нет проблем. Но у меня проблема с дизайном выражения для первой строки. Имя Reset Reason test - всего лишь пример теста, количество слов в нем может меняться, поэтому я не могу определить здесь какой-либо, более конкретный шаблон, а затем только .*.Отрицательное утверждение lookahead в python

12.07.2016 13:54:20 SCR_OUTPUT: #### TC_0006 Reset Reason test 
12.07.2016 13:54:20 SCR_OUTPUT: #### TC_0006 Reset Reason test done. 

Я имею регулярное выражение, как правило, делать, что я хочу, чтобы это сделать:

([0-9:. ]*) SCR_OUTPUT: #### (TC_[a-fA-F0-9]{4,5}[:0-9]{0,4}) .*[ ](?!done\.$) 

И у меня есть два случая, которые я хочу, чтобы дифференцировать: I, основанные на примере, приведенном здесь. https://docs.python.org/3/howto/regex.html#lookahead-assertions

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

[.](?!done$) 

Когда я пытаюсь, чтобы это было что-то, что меня устраивает больше, например: (мой done. имеет точка на конце)

[.](?!done\.$) 

Тогда это становится странным. Другая адаптация. done. должно сопровождаться пробелом, а не точкой, и результат становится сумасшедшим. Каждая строка дает положительные результаты.

[.](?!done\.$) 

Я проверял, что на pythex.org. По этой ссылке вы можете найти последнюю версию моего эксперимента.

Кто-нибудь знает, где у меня ошибка? Можно ли так спровоцировать такой случай? Возможно, я должен сделать это за два шага?

+0

Вы хотите, чтобы сбой завершился после того, как строка/строка заканчивается 'done.'? ['^ ([0-9 :.] *). * SCR_OUTPUT: #### (TC_ [a-fA-F0-9] {4,5} [: 0-9] {0,4}) (?!. * done \. $). * '] (https://regex101.com/r/nI7eQ2/1)? –

+0

Или ['^ (?!. * Done \. $) ([0-9.] + \ S + [\ d:] +) \ s + SCR_OUTPUT: \ s * #### \ s * (TC_ \ w +). * '] (https://regex101.com/r/nI7eQ2/2) (что быстрее)? –

+0

Точно. Всякий раз, когда строка с «сделано». дано, он должен потерпеть неудачу. – user2362824

ответ

1

Если вы хотите исключить совпадающие строки с done. в конце концов, вы должны использовать отрицательный предпросмотр, а лучше на якорь в начале линии:

^(?!.* done\.$)([0-9.]+\s+[\d:]+)\s+SCR_OUTPUT:\s*####\s*(TC_\w+).* 
^^^^^^^^^^^^^^ 

Смотрите regex demo (не забудьте использовать re.M флаг ^ соответствует началу строки, а не началу строки, если у вас есть многострочный ввод строки).

Примечание. Я улучшил шаблон регулярных выражений для строк, которые вы поставили (исходная часть, обращенная к ([0-9.]+\s+[\d:]+)\s+, значительно уменьшает обратную трассировку, вам следует подумать об использовании чего-то подобного, если этот точный шаблон не соответствует всем вашим данным).

Во всяком случае, основная точка интереса является опережением (?!.* done\.$), что сразу не проходит матч, когда он проверяет, есть ли пространство + done. в конце (done.) после 0+, кроме символа новой строки, как можно больше (символов .*).

+0

Спасибо. Это именно то, что делает эта работа. Этот урок я не видел ни в одном примере. – user2362824

+0

В случае даты время я ставлю кратчайший возможный шаблон, просто чтобы сделать его коротким. Эта часть была во всяком случае неважной в моей проблеме. Но спасибо за совет, я это рассмотрю. – user2362824

+0

Да, вы можете использовать '[0-9 .:] +', чтобы сделать его «короче», но '. *' Befire 'SCR_OUTPUT' был излишним. Кроме того, имейте в виду, что «более короткий» не означает «более эффективный» и почти никогда не означает «более точное» в мире регулярных выражений. –

Смежные вопросы