escaping "\" in the end of a string in tcl - tcl

I want to create a string that ends with "\". For example:
set str {",$"23"^##$\'"\}
This won't work because tcl thinks that I'm escaping the "}" here.
So I tried to escape the "\"
set str {",$"23"^##$\'"\\}
but now the value of str is ",$"23"^##$\'"\\.
I want the value of str to be with one "\" in the end: ",$"23"^##$\'"\
How can I do that while creating the string inside {}

The easiest way I could think is to use format:
puts [format {",$"23"^##$\'"%s} \\]
",$"23"^##$\'"\
I think you could even try with the %c and the ascii code of the \.

You can't; this is one of the small number of cases that can't be quoted that way. Here's the proof from an interactive session:
% gets stdin s
",$"23"^##$\'"\
15
% list $s
\",\$\"23\"^##\$\\'\"\\
Other such cases are thing like where there's unbalanced braces, and so on. They really don't come up very often. That backslash form above generated by list is the alternative (and you can put it in double quotes if you wish).

Related

How do I convert MS Smart quotes “ into ascii? using Tool command language (TCL)

I used the following but it does not recognize the smart quotes
set EmailSubject [string map -nocase {“ \\u0093 } $EmailSubject]
I am using TCL
There are several issues here.
What is \u0093 doing there? That's a control character.
\u.... will not be converted when inside braces.
-nocase is not needed, alpha characters are not being converted.
I recommend using the \u.... format rather than embedding the “ characters.
I am also going to make an assumption that by "converting into ascii", you want the ordinary " character. If this is wrong, please update your question.
The characters to convert are \u201C and \u201D, the left and right curly quotation marks. So the string map command will look like:
set EmailSubject [string map [list \u201C \" \u201D \"] $EmailSubject]
This converts both \u201C and \u201D into the " character.

regsub 1 space between words to "_"

Can anyone help to regsub 1 space between words to "_" (TCL)?
The original line:
CTS__94331/I (DCCKBD8BWP240H11P57PDULVT) 0.025 0.002 & 0.352 r
The require line:
CTS__94331/I_(DCCKBD8BWP240H11P57PDULVT) 0.025 0.002_& 0.352_r
I tried the below but each space replaced to "" and I want only 1 space to replace to ""
regsub -all {\s{1}} $a _
You need to be sneakier in your regular expression and use a different replacement.
regsub -all {(\S)\s(?=\S)} $a {\1_}
The regular expression matches (and captures) a non-whitespace followed by a whitespace and then requires (with a lookahead constraint) that the next character is a non-whitespace without matching it. This is replaced with the first character you matched (replacing it with itself) and the underscore.
Normally for this sort of thing you'd use \y\s\y → _, but that doesn't work in your use case because it doesn't handle 0.002 & correctly (& is not a word character).
If Tcl's RE engine supported lookbehind constraints (it doesn't) this would be much simpler to solve as you wouldn't need the trickery of replacing the character before the space with itself.
regsub 1 space between words to "_"
For this case, you may consider string map:
% string map {" " "_"} {CTS__94331/I (DCCKBD8BWP240H11P57PDULVT)}
CTS__94331/I_(DCCKBD8BWP240H11P57PDULVT)
However, your example data is inconsistent and I do not see an example of more than one whitespace to be come replaced?

Interpolating a JSON string removes JSON quotations

I have the following two lines of code:
json_str = _cases.to_json
path += " #{USER} #{PASS} #{json_str}"
When I use the debugger, I noticed that json_str appears to be formatted as JSON:
"[["FMCE","Wiltone","Wiltone","04/10/2018","Marriage + - DOM"]]"
However, when I interpolate it into another string, the quotes are removed:
"node superuser 123456 [["FMCE","Wiltone","Wiltone","04/10/2018","Marriage + - DOM"]]"
Why does string interpolation remove the quotes from JSON string and how can I resolve this?
I did find one solution to the problem, which was manually escaping the string:
json_str = _cases.to_json.gsub('"','\"')
path += " #{USER} #{PASS} \"#{json_str}\""
So basically I escape the double quotes generated in the to_json call. Then I manually add two escaped quotes around the interpolated variable. This will produce a desired result:
node superuser 123456 "[[\"FMCE\",\"Wiltone\",\"Wiltone\",\"04/10/2018\",\"Marriage + - DOM\"]]"
Notice how the outer quotes around the collection are not escaped, but the strings inside the collection are escaped. That will enable JavaScript to parse it with JSON.parse.
It is important to note that in this part:
json_str = _cases.to_json.gsub('"','\"')
it is adding a LITERAL backslash. Not an escape sequence.
But in this part:
path += " #{USER} #{PASS} \"#{json_str}\""
The \" wrapping the interpolated variable is an escape sequence and NOT a literal backslash.
Why do you think the first and last quote marks are part of the string? They do not belong to the JSON format. Your program’s behavior looks correct to me.
(Or more precisely, your program seems to be doing exactly what you told it to. Whether your instructions are any good is a question I can’t answer without more context.)
It's hard to tell with the small sample, but it looks like you might be getting quotes from your debugger output. assuming the output of .to_json is a string (usually is), then "#{json_str}" should be exactly equal to json_str. If it isn't, that's a bug in ruby somehow (doubtful).
If you need the quotes, you need to either add them manually or escape the string using whatever escape function is appropriate for your use case. You could use .to_json as your escape function even ("#{json_str.to_json}", for example).

How to trim two words from right of a string

I want to remove two words from right of a string.
For example:
set str "sachin is the pride of india"
I need to remove india and of from right and there should be no space after that.
I have tried using string trimright.
The string trimright command is exactly the wrong tool for this; it treats its trim argument as a set of characters to remove, not a literal. The simplest way of doing this is with lreplace, provided the string doesn't contain list metacharacters and you don't care about the number of spaces.
set shortened [lreplace $str end-1 end]
If you need to do it reliably, regular expressions are the tool of choice.
set shortened [regsub {\s*\S+\s+\S+\s*$} $str ""]
Use regsub for this. Please.

Is there any Tcl function to add escape character automatically?

Is there any Tcl function to add escape character to a string automatically?
For example, I have a regular expression
"[xy]"
After I call the function, I get
"\[xy]"
After being called again, I get
"\\\[xy]"
I remember there's such function with some script language, but I cannot recall which language it is.
The usual way of adding such escape characters as are “necessary” is to use list (% is my Tcl prompt):
% set s {[xy]}
[xy]
% set s [list $s]
{[xy]}
% set s [list $s]
{{[xy]}}
The list command prefers to leave alone if it can, wrap with braces if it can get away with it, and resorts to backslashing otherwise (because backslashes are really unreadable).
If you really need backslashes, string map or regsub will do what you need. For example:
set s [regsub -all {\W} $s {\\&}]