我有以下模式
Pattern[1]:
Key : "key1"
Value : 100
Pattern[2]:
Key : "key2"
Value : 20
Pattern[3]:
Key : "key3"
Value : 30
Pattern[4]:
Key : "key4"
Value : 220
我想隔离每个Pattern
块。我正在使用TCL。我正在使用的Regexp无法解决目的
set updateList [regexp -all -inline {Pattern\[\d+\].*?Value.*?\n} $list]
使用哪个Regexp来隔离每个模式
我需要输出
Pattern[1]:
Key : "key1"
Value : 100
Pattern[2]:
Key : "key2"
Value : 20
Pattern[3]:
Key : "key3"
Value : 30
Pattern[4]:
Key : "key4"
Value : 220
答案 0 :(得分:2)
您的模式Pattern\[\d+\].*?Value.*?\n
包含混合量词:贪婪和懒惰。 Tcl不像你期望的那样处理混合量词类型,比如PCRE(PHP,Perl),.NET等,它默认为第一个找到的,因为后续的量词继承了前面的量词类型。因此,+
之后的\d
是贪婪的,因此,所有其他人(在.*?
中)也是贪婪的 - 即使你宣称它们是懒惰的。此外,.
也匹配Tcl正则表达式中的换行符,因此,您的模式就像this一样。
因此,根据您的正则表达式,您可以使用\d+
使\d+?
延迟,并使用\n
替换(?:\n|$)
,以匹配换行符和字符串的结尾:
set RE {Pattern\[\d+?\].*?Value.*?(?:\n|$)}
set updateList [regexp -all -inline $RE $str]
请参阅IDEONE demo
备选方案1
此外,如果您的输入字符串始终与所有元素具有相同的结构,则可以使用更详细的正则表达式 - Pattern
,Key
,Value
- 现在:
set updateList [regexp -all -inline {Pattern\[\d+\]:\s*Key[^\n]*\s*Value[^\n]*} $str]
请参阅IDEONE demo,此处为regex demo。
由于.
可以匹配换行符,因此我们需要使用[^\n]
否定字符类来匹配除换行符之外的任何字符。
备选方案2
您可以使用与Pattern[n]:
匹配的展开的延迟子模式,然后使用不是Pattern[n]:
序列起点的任何字符:
set RE {Pattern\[\d+\]:[^P]*(?:P(?!attern\[\d+\]).)*}
set updateList [regexp -all -inline $RE $str]
答案 1 :(得分:1)
试试这个
Pattern\[\d+\](.|\n)*?Value.*?\n
点。字符匹配任何字符但换行符,因此您需要将其添加进去。请注意,您的行可能以滑块字符结尾,因此您可能需要添加 \ r in。
答案 2 :(得分:1)
您想要捕获线条块并输出它们之间的空白行。您的示例数据显示不同级别的模式,可用于识别哪些行属于哪个块。
最简单的模式是:输入中的每三行组成一个块。这种模式建议像这样处理:
set lines [split [string trim $list \n] \n]
foreach {a b c} $lines {puts $a\n$b\n$c\n\n}
您的示例数据中没有任何内容表明这不起作用。尽管如此,可能会有一些并发症未在您的示例数据中反映出来。
如果输入中有空行,则可能需要先删除它们:
set lines [lmap line $lines {if {[string is space $line]} continue else {set line}}]
如果某些块包含的行数少于或少于示例,则另一个简单模式是每个块都以一个具有可选(?)空格和单词Pattern
的行开头。这些行(第一行除外)应在输出中以块分隔符开头:
set lines [split [string trim $list \n] \n]
puts [lindex $lines 0]
foreach line [lrange $lines 1 end] {
if {[regexp {\s*Pattern} $line]} {
puts \n$line
} else {
puts $line
}
}
puts \n
如果这些行实际上不是以空格开头,则可以使用string match Pattern* $line
而不是正则表达式。
文档:continue,foreach,if,lindex,lmap,lmap替代,lrange,{{ 3}},puts,regexp,set,split
答案 3 :(得分:1)
% set list { Pattern[1]:
Key : "key1"
Value : 100
Pattern[2]:
Key : "key2"
Value : 20
Pattern[3]:
Key : "key3"
Value : 30
Pattern[4]:
Key : "key4"
Value : 220
}
% regexp -all -inline {Pattern\[\d+\].*?Value.*?\n} $list
{Pattern[1]:
Key : "key1"
Value : 100
Pattern[2]:
Key : "key2"
Value : 20
Pattern[3]:
Key : "key3"
Value : 30
Pattern[4]:
Key : "key4"
Value : 220
}
% regexp -all -inline {Pattern\[\d+?\].*?Value.*?\n} $list ;# only changing `\d+` to `\d+?`
{Pattern[1]:
Key : "key1"
Value : 100
} {Pattern[2]:
Key : "key2"
Value : 20
} {Pattern[3]:
Key : "key3"
Value : 30
} {Pattern[4]:
Key : "key4"
Value : 220
}
如果$ list 不以换行符结尾,则您无法获得"模式[4]"元素返回。在这种情况下,请更改
% regexp -all -inline {Pattern\[\d+?\].*?Value.*?\n} $list
到
% regexp -all -inline {Pattern\[\d+?\].*?Value.*?(?:\n|$)} $list