Что это регулярное выражение пытается сопоставить?

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

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

person Community    schedule 17.04.2012    source источник
comment
на каком языке вы пишете это регулярное выражение?   -  person Philip C    schedule 17.04.2012
comment
похоже, что все языки программирования используют одни и те же правила для регулярных выражений?   -  person    schedule 17.04.2012
comment
@ratzip не соответствует действительности; Взгляните на различия между POSIX BRE / ERE и PCRE среди других разновидностей. en.wikipedia.org/wiki/Regular_expression   -  person cmbuckley    schedule 17.04.2012
comment
Это регулярное выражение требует 2 символа после группы захвата. Вместо этого вам может понадобиться следующее: .(?:$|\[^\\n]) чтобы попасть в конец строки или символ, не являющийся новой строкой.   -  person glenn jackman    schedule 17.04.2012


Ответы (2)


Если вы не экранируете символы, вы получите следующее:

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

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

Принимая все это во внимание, получается, что это регулярное выражение извлекает серию цифр из середины строки. Учитывая формат чисел, он может искать метку времени в формате 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

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

Интересная часть TCL заключается в том, что вам нужно экранировать символ [, но не ], в то время как { и } нужно экранировать.

person bta    schedule 17.04.2012
comment
Вы бы сопоставили что-то в этом формате - 333:333:333-54322, например, с e=(.), соответствующим любым символам, кроме разрыва строки. То же самое касается ([^\n]). - person Dennis Rongo; 17.04.2012
comment
Определение регулярного выражения было бы намного легче читать, если бы первоначальный программист просто использовал {} вместо . {} внутри него сбалансированы, поэтому они не вызовут проблем, и это будет означать гораздо меньше побегов. - person RHSeeger; 17.04.2012
comment
Для RE Tcl [\d] и \d полностью эквивалентны. - person Donal Fellows; 17.04.2012

person    schedule
comment
\\d на самом деле экранирует char d, поэтому он больше не захватывает цифры, а буквально ищет букву d в этом случае. - person Dennis Rongo; 17.04.2012
comment
@ Деннис Ронго - Неправда. Когда команда обрабатывается, один слой побегов удаляется. Последовательность \[\\d] видится как [\d], когда механизм регулярных выражений получает ее, поэтому она будет соответствовать цифре, а не букве 'd'. См. мой ответ для примеров (вы можете добавить puts $re, чтобы увидеть выражение после обработки побегов). - person bta; 17.04.2012