这些天我正在学习regular expressions,但对我来说似乎有点困难。我正在阅读TCL中的一些代码,但它想要匹配什么?
regexp ".* (\[\\d]\{3\}:\[\\d]\{3\}:\[\\d]\{3\}.\[\\d]\{5\}).\[^\\n]" $input
答案 0 :(得分:8)
如果您取消转义字符,则会收到以下内容:
.* ([\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
命令的详细信息,请参阅the TCL wiki。
TCL的有趣之处在于你必须逃避[
字符,而不是]
,而{
和}
都需要转义。
答案 1 :(得分: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