In Tcl list element in quotes followed by ")" instead of space

1.2k Views Asked by At

This question maybe the duplicate of this question but the problem that I'm facing is not relevant to that answer. I have tried the code what people posted there but I can't achieve what I want. My code:

set line H_Dev: Issue with DELETE funtion in OSPF OC (Input List is missing required key "identifier") 
foreach {name value} [string map {( { } ) {} } $line] {
    puts "$name $value"
}

above code not working but after I include { }

set line {H_Dev: Issue with DELETE funtion in OSPF OC (Input List is missing required key "identifier")} 

its working like this

H_Dev: Issue
with DELETE
funtion in
OSPF OC
Input List
is missing
required key
identifier

but in my script the $line is in list only. how to get the plain text like this

H_Dev: Issue with DELETE funtion in OSPF OC Input List is missing required key identifier
2

There are 2 best solutions below

0
On

The problem is this line:

set line H_Dev: Issue with DELETE funtion in OSPF OC (Input List is missing required key "identifier") 

Since you've not quoted anything, you are passing many arguments to set (which would error as it doesn't take that many arguments), or would be except that "identifier") looks like it is a double-quoted word, except it doesn't because of the ) after the closing " and that's the cause of the error.

The usual fixes are to either double-quote the whole string (with backslashes before any internal double quotes):

set line "H_Dev: Issue with DELETE funtion in OSPF OC (Input List is missing required key \"identifier\")"

or to put the whole lot in braces (which nest, making it very easy):

set line {H_Dev: Issue with DELETE funtion in OSPF OC (Input List is missing required key "identifier")}

To get just the words you want, you can use string map to remove the unwanted characters, regsub -all to remove the unwanted characters, or regexp -all -inline to pick out the wanted words.

Option one:

set line [string map {{"} {} ( {} ) {}} $line]

Option two:

set line [regsub -all {[("")]} $line ""]

Option three:

set line [regexp -all -inline {[\w]+:?} $line]

I tend to prefer to pick out the words that I want instead of filtering the characters that I don't want, as that is less surprising with unexpected inputs. Other people disagree with me.

0
On

You are correct that you need braces (or quotes, which wouldn't work well in your case because you have quotes in the string) around your string if you want to assign it to a variable with a "set" command. If you don't have braces then this passes too many arguments to the "set" command. The problem is this:

foreach {name value} [string map {( { } ) {} } $line] {
  puts "$name $value"
}

This is going through your string two words at a time, assigning them to the variables "name" and "value" and printing each pair on a single line. If you just want to print the entire string, get rid of the foreach line and just do this:

puts $line

If you're also trying to get rid of parens and braces (which is what it looks like from your code), you could do this:

puts [string map {( { } ) {} } $line]