1

这些天我正在学习正则表达式,但这对我来说似乎有点难。我正在阅读 TCL 中的一些代码,但它想要匹配什么?

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

2 回答 2

8

如果你取消转义字符,你会得到以下信息:

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

该术语[\d]{x}将匹配x连续数字的数量。因此,括号内的部分将匹配某种形式###:###:###?#####(其中#可以是任何数字,?也可以是任何字符)。括号本身不匹配,它们仅用于指定输入的哪一部分“捕获”并返回给调用者。在这个序列之后是一个点.,它匹配一个字符(可以是任何字符)。尾随将匹配换行符以外的[^\n]任何单个字符(括号表达式开头的 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

前两个示例与表达式匹配。第三个失败,因为它在第一个数字序列之前缺少空格字符。第四个失败,因为它在尾随空格之后的末尾没有非换行符。第五个失败是因为数字序列没有足够的数字。通过在输入之后传递参数,您可以存储与表达式匹配的输入部分以及使用括号“捕获”的数据。有关该命令的详细信息,请参阅TCL wiki 。regexp

TCL 的有趣之处在于您必须转义[字符而不是],而{and都}需要转义。

于 2012-04-17T15:42:56.353 回答
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
于 2012-04-17T15:32:15.640 回答