2012-04-17 2 views
1

В эти дни я изучаю regular expressions, но мне кажется, что это немного сложно. Я читаю код в TCL, но что он хочет совместить?Что это регулярное выражение пытается сопоставить?

regexp ".* (\[\\d]\{3\}:\[\\d]\{3\}:\[\\d]\{3\}.\[\\d]\{5\}).\[^\\n]" $input 
+0

На каком языке вы пишете это регулярное выражение? –

+0

кажется, что все языки программирования используют те же правила для регулярных выражений? –

+1

@ratzip не соответствует действительности; Посмотрите различия между POSIX BRE/ERE и PCRE, среди других вкусов. http://en.wikipedia.org/wiki/Regular_expression – cmbuckley

ответ

8

Если вы отмените избежать символов, вы получите следующее:

.* ([\d]{3}:[\d]{3}:[\d]{3}.[\d]{5}).[^\n]

Термин [\d]{x} будет соответствовать x число последовательных цифр. Поэтому часть внутри круглых скобок будет соответствовать чему-то вроде формы ###:###:###?##### (где # может быть любой цифрой и ? может быть любым символом). Скобки не совпадают, они просто используются для указания того, какая часть ввода «захвата» и возврата к вызывающему. После этой последовательности находится одна точка ., которая соответствует одному символу (который может быть любым). Конечный [^\n] будет соответствовать одному символу, который является чем-то , за исключением a newline (a ^ в начале выражения в квадратных скобках инвертирует совпадение). Термин .* в самом начале соответствует последовательности символов любой длины (даже нулевой), за которой следует пробел.

С учетом всего этого, похоже, это регулярное выражение извлекает серию цифр из середины строки. Учитывая формат чисел, он может искать временную метку в формате hours:minutes:seconds.milliseconds (хотя, если это так, вместо этого следует использовать {1,3} и {1,5}). Заключительный термин .[^\n] выглядит так, будто он может пытаться исключить отметки времени, которые находятся на конце линии или рядом с ней. Временные журналы часто имеют временную метку, за которой следует какой-то разделительный символ (:, >, пробел и т. Д.). Такое регулярное выражение может быть использовано для извлечения временных меток из журнала при игнорировании «пустых» строк с меткой времени, но без сообщения.

Обновление: Ниже приведен пример с использованием TCL 8.4:

% set re ".* (\[\\d]\{3\}:\[\\d]\{3\}:\[\\d]\{3\}.\[\\d]\{5\}).\[^\\n]" 
% regexp $re "TEST: 123:456:789:12345> sample log line" 
1 
% regexp $re " 111:222:333.44444 foo" 
1 
% regexp $re "111:222:333.44444 foo" 
0 
% regexp $re " 111:222:333.44444 " 
0 
% regexp $re " 10:44:56.12344: " 
0 
% 
% regexp $re "TEST: 123:456:789:12345> sample log line" match data 
1 
% puts $match 
TEST: 123:456:789:12345> 
% puts $data 
123:456:789:12345 

Первые два примера соответствуют выражению. Третий не работает, потому что ему не хватает символа пробела перед первой последовательностью чисел. Четвертый терпит неудачу, потому что после конечного пробела он не имеет символа без символа новой строки. Пятый не работает, потому что числовые последовательности не имеют достаточного количества цифр. Пропуская параметры после ввода, вы можете сохранить часть входа, которая соответствовала выражению, а также данные, которые были «захвачены» с помощью круглых скобок. См. the TCL wiki для получения дополнительной информации о команде regexp.

Интересная часть с TCL является то, что вы должны избежать [ характер, но не ], в то время как { и } необходимость побега.

+0

Вы сопоставляете что-то в этом формате - «333: 333: 333-54322eg» с e = («.»), Сопоставляя любые символы, кроме разрыва строки. То же самое касается ("[^ \ n]"). –

+2

Определение regexp было бы намного легче читать, если бы оригинальный программист только что использовал {} вместо "". {} Внутри него сбалансированы, поэтому они не вызовут проблемы, и это будет означать гораздо меньшую выгоду. – RHSeeger

+0

Отличная запись. – RHSeeger

0
.* ==> match junk part of the input 

(==> start capture 

\[\\d]\{3\}: ==> match 3 digits followed by ':' 

\[\\d]\{3\}: ==> match 3 digits followed by ':' 

\[\\d]\{3\}. ==> match 3 digits followed by any character 

\[\\d]\{5\} ==> match 5 digits 

). ==> close capture and match any character 

\[^\\n] ==> match a character that is not a newline 
+0

«\\ d» фактически ускользает от символа d, так что это больше не записывает цифры, а буквально ищет букву «d» в этом случае. –

+3

@ DennisRongo- Не правда. Когда команда обрабатывается, один слой экранов удаляется. Последовательность '\ [\\ d]' рассматривается как '[\ d]', когда движок regex получает его, поэтому это будет соответствовать цифре, а не букве 'd'. См. Мой ответ для примеров (вы можете добавить 'puts $ re', чтобы увидеть выражение после обработки escape-запросов). – bta

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