将 regsub 中的匹配项与 & 传递给过程(正在使用 Tcl)
Passing a match in regsub with & to a procedure (Tcl is being used)
我想遍历逗号分隔的字符串并用更多逗号分隔的元素替换匹配项。
即 regsub 之后的 5-A,B 应该给我 1-A,2-A,3-A,4-A,5-A,B
以下内容对我不起作用,因为 & 作为实际 & 而不是实际匹配项传递:
regsub -all {\d+\-\w+} $string [myConvertProc &]
但是不尝试传递 & 并直接使用它有效:
regsub -all o "Hello World" &&&
> Hellooo Wooorld
不确定我在尝试将值传递给 myConvertProc
时做错了什么
编辑: 我认为我最初的问题是 [myConvertProc &] 首先被评估,所以我实际上是通过 '& ' 到程序。
如何在正则表达式领域解决这个问题?可能吗?
编辑 2: 我已经在拆分列表上使用 foreach 解决了它,所以我只是想看看如果这在 regsub 中是可能的。谢谢!
您在第一次编辑时是正确的:问题是 regsub
的每个参数在执行命令之前都已完全评估。
一种解决方案是在字符串中插入命令替换字符串,然后在其上使用subst
:
set string [regsub -all {\d+\-\w+} $string {[myConvertProc &]}]
# -> [myConvertProc 5-A],B
set string [subst $string]
# -> 1-A,2-A,3-A,4-A,5-A,B
这只有在 string
中没有其他内容需要替换的情况下才有效(但您当然可以关闭变量和反斜杠替换)。
foreach
解决方案要好得多。另一种 foreach
解决方案是遍历 regexp -indices -inline -all
的结果,但如果可行,最好遍历拆分列表的各个部分。
更新:
典型的 foreach
解决方案如下:
set res {}
foreach elem [split $string ,] {
if {[regexp -- {^\d+-\w+$} $elem]} {
lappend res [myConvertProc $elem]
} else {
lappend res $elem
}
}
join $res ,
也就是说,您通过查看原始列表中的每个元素来收集结果列表。如果该元素符合您的要求,则将其转换并将结果添加到结果列表中。如果元素不匹配,您只需将其添加到结果列表即可。
在 Tcl 8.6 中可以稍微简化一下:
join [lmap elem [split $string ,] {
if {[regexp -- {^\d+-\w+$} $elem]} {
myConvertProc $elem
} else {
set elem
}
}] ,
这是一回事,但 lmap
命令会为您处理结果列表。
文档:foreach, lappend, lmap, regexp, regsub, set, split, subst
我想遍历逗号分隔的字符串并用更多逗号分隔的元素替换匹配项。
即 regsub 之后的 5-A,B 应该给我 1-A,2-A,3-A,4-A,5-A,B
以下内容对我不起作用,因为 & 作为实际 & 而不是实际匹配项传递:
regsub -all {\d+\-\w+} $string [myConvertProc &]
但是不尝试传递 & 并直接使用它有效:
regsub -all o "Hello World" &&&
> Hellooo Wooorld
不确定我在尝试将值传递给 myConvertProc
时做错了什么编辑: 我认为我最初的问题是 [myConvertProc &] 首先被评估,所以我实际上是通过 '& ' 到程序。
如何在正则表达式领域解决这个问题?可能吗?
编辑 2: 我已经在拆分列表上使用 foreach 解决了它,所以我只是想看看如果这在 regsub 中是可能的。谢谢!
您在第一次编辑时是正确的:问题是 regsub
的每个参数在执行命令之前都已完全评估。
一种解决方案是在字符串中插入命令替换字符串,然后在其上使用subst
:
set string [regsub -all {\d+\-\w+} $string {[myConvertProc &]}]
# -> [myConvertProc 5-A],B
set string [subst $string]
# -> 1-A,2-A,3-A,4-A,5-A,B
这只有在 string
中没有其他内容需要替换的情况下才有效(但您当然可以关闭变量和反斜杠替换)。
foreach
解决方案要好得多。另一种 foreach
解决方案是遍历 regexp -indices -inline -all
的结果,但如果可行,最好遍历拆分列表的各个部分。
更新:
典型的 foreach
解决方案如下:
set res {}
foreach elem [split $string ,] {
if {[regexp -- {^\d+-\w+$} $elem]} {
lappend res [myConvertProc $elem]
} else {
lappend res $elem
}
}
join $res ,
也就是说,您通过查看原始列表中的每个元素来收集结果列表。如果该元素符合您的要求,则将其转换并将结果添加到结果列表中。如果元素不匹配,您只需将其添加到结果列表即可。
在 Tcl 8.6 中可以稍微简化一下:
join [lmap elem [split $string ,] {
if {[regexp -- {^\d+-\w+$} $elem]} {
myConvertProc $elem
} else {
set elem
}
}] ,
这是一回事,但 lmap
命令会为您处理结果列表。
文档:foreach, lappend, lmap, regexp, regsub, set, split, subst