Hi I am new to tcl and want to assign "\n" to a variable and use that variable in regsub to replace that string.
It should be like :
set a "\n\[\"this is my code\"\]"
puts $a
I was expecting this will give
\n\[\"this is my code\"\], then I could use this $a in regsub {$a} $str "replace" sub_str.
This regsub could search $a inside $str and replace the matching one with replace and strore it in sub_str.
However, it gave me [this is my code]
Is there a way I could get the 1st format as \n\[\"this is my code\"\] so I could use that to do the string regsub?
Thanks!
Use braces instead of quotes to prevent evaluation of the backslash escapes:
set a {\n\[\"this is my code\"\]}
puts $a
prints
\n\[\"this is my code\"\]
Related
I want to convert both strings into SML_CHAINS_6_* using regsub in tcl. How do I do that?
SML_CHAINS_6_1167
SML_CHAINS_6_1145
Something like:
set var1 SML_CHAINS_6_1167
regsub {\d+$} $var1 "*" var1
and same for the other. Just replacing all trailing digits with a single asterisk.
I am getting missing closing brace error for the line
set text [join $text \n]
my entire code is
proc ProcessText { text} {
regsub -all -- ({) $text {\{} text
set text [join $text \n]
return $text
}
##it starts from here
set text "{a b c"
puts $text
puts [ProcessText $text]
If I am using regsub to replace the { to any proper substitution that will not throw error, I am getting error
"Missing close-brace while executing"proc ProcessText {}"
if I comment regsub then I get error
"unmatched open brace in list while executing
"join $text \n"
Can anyone please suggest me here how to proceed for the same in tcl.
FYI:
text is a list which contains lot of textual information in which a { is also there, if i remove the {. It works other wise not.
As Donal has sensed already, it is the formatting of the value hold by variable text that does not conform to a Tcl list, which is expected by [join], however.
Your options are:
1) Turn the value into a Tcl list by using [split]:
join [split $text] \n
2) Avoid the conversion into a list and [join] altogether by using [string map]:
string map {" " "\n"} $text
(or use [regsub] as below, if you can't control white-space proliferation in your input)
Sometimes, a string better stays just a string ;)
Varia
Your use of [regsub] is problematic, foremost, better use it once to obtain your ultimate goal, rather than sanitizing the input string before calling [join]:
regsub -all {\s+} $text "\n"
Background
You run into errors because you do not escape the sentinel { in the regular expression ({) to [regsub] correctly:
regsub -all -- ({) $text {\{} text
This should be:
regsub -all -- {\{} $text {\{} text
In your variant, { is considered an opening brace that is, actually, not matched in the remainder of the script.
I am new to tcl, trying to learn, need a help for below.
My string looks like in configFileBuf and trying to replace second occurance of ConfENB:local-udp-port>31001" with XYZ, but below regsub cmd i was tried is always replacing with first occurance (37896). Plz help how to replace second occurance with xyz.
set ConfigFileBuf "<ConfENB:virtual-phy>
</ConfENB:local-ip-addr>
<ConfENB:local-udp-port>37896</ConfENB:local-udp-port>
</ConfENB:local-ip-addr>
<ConfENB:local-udp-port>31001</ConfENB:local-udp-port>
</ConfENB:virtual-phy>"
regsub -start 1 "</ConfENB:local-ip-addr>\[ \n\t\]+<ConfENB:local-udp-port>\[0-9 \]+</ConfENB:local-udp-port>" $ConfigFileBuf "XYZ" ConfigFileBuf
puts $ConfigFileBuf
You have to use regexp -indices to find where to start the replacement, and only then regsub. It's not too bad if you put the regular expression in its own variable.
set RE "</ConfENB:local-ip-addr>\[ \n\t\]+<ConfENB:local-udp-port>\[0-9 \]+</ConfENB:local-udp-port>"
set start [lindex [regexp -all -indices -inline $RE $ConfigFileBuf] 1 0]
regsub -start $start RE $ConfigFileBuf "XYZ" ConfigFileBuf
The 1 is the number of submatches in the RE (zero in this case) plus 1. You can compute it with the help of regexp -about, giving this piece of trickiness:
set RE "</ConfENB:local-ip-addr>\[ \n\t\]+<ConfENB:local-udp-port>\[0-9 \]+</ConfENB:local-udp-port>"
set relen [expr {1 + [lindex [regexp -about $RE] 0]}]
set start [lindex [regexp -all -indices -inline $RE $ConfigFileBuf] $relen 0]
regsub -start $start RE $ConfigFileBuf "XYZ" ConfigFileBuf
If your string was well-formed XML I'd suggest something like tDOM to manipulate it. DOM-style manipulation is almost always better than regular expression-based manipulation on XML markup. (I mention this on the off chance that it's actually supposed to be XML and you just quoted it wrong.)
It looks like you're trying to use -start 1 to tell regsub to skip the first match. The starting index is actually a character index, so in this invocation regsub will just skip the first character in the string. You could set -start further into your string, but that's fragile unless you use regexp to calculate where the first match ends.
I think the best solution would be to get a list of indices to matches by invoking regexp with -all -inline -indices, pick out the second index pair using lindex and finally use string replace to perform the substitution, like this:
set pattern {</ConfENB:local-ip-addr>[ \n\t]+<ConfENB:local-udp-port>[0-9 ]+</ConfENB:local-udp-port>}
set matches [regexp -all -inline -indices -- $pattern $ConfigFileBuf]
set match [lindex $matches 1]
set ConfigFileBuf [string replace $ConfigFileBuf {*}$match XYZ]
The variable match contains a pair of indices (start and end, respectively) for the range of characters you want to replace. As string replace expects those indices to be in different arguments you need to expand $match with the {*} prefix. If you have an earlier version of Tcl than 8.5, you need a slight change to the above code:
foreach {start end} $match break
set ConfigFileBuf [string replace $ConfigFileBuf $start $end XYZ]
In passing, note that you can avoid escaping e.g. character sets in a regular expression if you quote it with braces instead of double quotes.
Documentation links: regexp, lindex, string
How to perform string mapping for a value stored in a variable?
Example:
I have my output in a variable say "a".
set a "a.b12.d4" (its unknown)
Is it possible to use string map to map contents of $a as "\t" in another variable say b?
like,
set c [string map {"contents of $a" "\t"}$b]
{I know $a cannot be used here. Is there a way to subtitute contents of $a here in string mapping?}
It is possible if you do not use curly braces as they prevent substitution:
set a "a.b12.d4"
set b "$a.123"
puts [string map [list $a \t] $b]
I was using the command 'string trimright' to trim my string but I found that this command trims more than required.
My expression is "dssss.dcsss" If I use string trim command to trim the last few characters ".dcsss", it trims the entire string. How can I deal with this?
Command:
set a [string trimright "dcssss.dcsss" ".dcsss"]
puts $a
Intended output:
dcsss
Actual output
""
The string trimright command treats its (optional) last argument as a set of characters to remove (and so .dcsss is the same as sdc. to it), just like string trim and string trimleft do; indeed, string trim is just like using both string trimright and string trimleft in succession. This makes it unsuitable for what you are trying to do; to remove a suffix if it is present, you can use several techniques:
# It looks like we're stripping a filename extension...
puts [file rootname "dcssss.dcsss"]
# Can use a regular expression if we're careful...
puts [regsub {\.dcsss$} "dcssss.dcsss" {}]
# Do everything by hand...
set str "dcssss.dcsss"
if {[string match "*.dcsss" $str]} {
set str [string range $str 0 end-6]
}
puts $str
If what you're doing really is filename manipulation, like it looks like, do use the first of these options. The file command has some really useful commands for working with filenames in a cross-platform manner in it.