0

I'm trying to use regsub in TCL to replace a string with the value from an array.

array set myArray "
one 1
two 2
"
set myString "\[%one%\],\[%two%\]"

regsub -all "\[%(.+?)%\]" $myString "$myArray(\\1)" newString

My goal is to convert a string from "[%one%],[%two%]" to "1,2". The problem is that the capture group index is not resolved. I get the following error:

can't read "myArray(\1)": no such element in array
while executing
"regsub -all "\[%(.+?)%\]" $myString "$myArray(\\1)" newString"
4

2 回答 2

1

This is a 2 step process in Tcl. Your main mistake here is using double quotes everywhere:

array set myArray {one 1 two 2}
set myString {[%one%],[%two%]}
regsub -all {\[%(.+?)%\]} $myString {$myArray(\1)} new
puts $new
puts [subst -nobackslash -nocommand $new]
$myArray(one),$myArray(two)
1,2

So we use regsub to search for the expression and replace it with the string representation of the variable we want to expand. Then we use the rarely-used subst command to perform the variable (only) substitution.

于 2013-10-30T23:42:09.753 回答
1

Apart from using regsub+subst (which is a decidedly tricky pair of commands to use safely in general) you can also do relatively simple transformations using string map. The trick is in how you prepare the mapping:

# It's conventional to use [array set] like this…
array set myArray {
    one 1
    two 2
}
set myString "\[%one%\],\[%two%\]"

# Build the transform
set transform {}
foreach {from to} [array get myArray] {
    lappend transform "\[%$from%\]" $to
}

# Apply the transform
set changedString [string map $transform $myString]
puts "transformed from '$myString' to '$changedString'"

As long as each individual thing you want to go from and to is a constant string at the time of application, you can use string map to do it. The advantage? It's obviously correct. It's very hard to make a regsub+subst transform obviously correct (but necessary if you need a more complex transform; that's the correct way to do %XX encoding and decoding in URLs for example).

于 2013-10-31T17:14:12.957 回答