我无法在regexp之后找到它, SCRIPT1:
set name_list {{Avg Speed} {Total Time(hr) }}
set lines {{Avg Speed|0.000} {Total Time(hr)|NA} }
set line_number 0
foreach line $lines {
incr line_number
foreach name $name_list {
puts "flag1: $name"
if { [regexp "^$name\\|(.+)$" $line matchVar value ] } {
puts "flag4: $value"
set rval($name) $value
set rval($name,line) $line_number
}
}
}
输出类似于:
输出1:
flag1: Avg Speed
flag4: 0.000
flag1: Total Time(hr)
flag1: Avg Speed
flag1: Total Time(hr)
如果我改变前2行,如:
SCRIPT2(修改):
set name_list {{Avg Speed} {Total Time}}
set lines {{Avg Speed|0.000} {Total Time|NA} }
我得到的是这样的:
Output2(想要输出像这样 - 实际输出)
flag1: Avg Speed
flag4: 0.000
flag1: Total Time
flag1: Avg Speed
flag1: Total Time
flag4: NA
那么,我应该如何修改我的正则表达式,以便我得到"(hr)"在第一个脚本中的output1 flag4处打印?
regexp "^$name\\|(.+)$" $line matchVar value
matchVar的目的是什么,因为这里匹配" 0.000& NA",但是怎么样?
答案 0 :(得分:1)
这是你的问题:你正在使用正则表达式,其中一个简单的字符串比较是合适的:
set name_list {{Avg Speed} {Total Time(hr)}} ;# <- note that I've shaved off space
set lines {{Avg Speed|0.000} {Total Time(hr)|NA}}
set line_number 0
foreach line $lines {
incr line_number
foreach name $name_list {
puts "flag1: $name"
lassign [split $line |] _name value
if {$_name eq $name} {
puts "flag4: $value"
set rval($name) $value
set rval($name,line) $line_number
}
}
}
文档: eq (operator), foreach, if, incr, lassign, puts, set, split
答案 1 :(得分:1)
matchVar
的目的是捕获RE匹配的整个子字符串;当你在两端锚定RE时,它与输入字符串相同(如果RE完全匹配)并且可能被忽略。当您的RE未经锚定或仅锚定在一侧时,当整体匹配(子)字符串为您提供有用信息时,它会更加相关。
你真正的问题是,你注入要搜索的RE的字符串本身有RE元字符; (hr)
被视为匹配hr
的子RE,并将其显示为regexp
可以报告的子匹配部分之一。要解决这个问题,我们需要在替换前向RE元字符添加反斜杠。我们可以使用regsub -all
来做到这一点,因为RE子语言保证所有元字符都不是字母数字“单词”字符,并且可以通过在它们前面加一个反斜杠来安全引用。
# ...
foreach name $name_list {
puts "flag1: $name"
# Replace all non-word characters with their backslashed form
regsub -all {\W} $name {\\&} REname
if { [regexp "^$REname\\|(.+)$" $line matchVar value ] } {
# ...