Use comment symbol in variable value TCL - tcl

I am looking to use the # symbol which is the symbol to indicate that everything following is going to be a comment in a variable value. So, I would like to write the following:
set Dev1_Number 1#
set Dev2_Number 2#
But the program only recognizes 1 and 2 as values that can be placed the memory location of the variable. Is there anyway to get around that?

Tcl comments only occur when the comment character is the first character of a command word
(http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm#M29). You'll see code with end-of-line comments preceded by a semicolon
set foo bar ;# this is a comment
set foo bar # this is an error!
That's not the case in your example. In your example, the hash is merely data.
Your comments indicate your editor is making an incorrect assumptions about Tcl syntax. What editor are you using?
If you are concerned, you can "force" the hash to be part of the value by using quotes
set Dev1_Number "1#"
set Dev1_Number {1#}

Use backslash character, It escapes the original meaning of that character.
set a 3\#
puts "a=$a"
output: a=3

Related

Tcl quoting proc to sanitise string to pass to other shells

I want to pass a dict value to another shell (in my application it passes through a few 'shell' levels), and the dict contains characters (space, double quotes, etc) that cause issues.
I can use something like ::base64::encode -wrapchar $dict and the corresponding ::base64::decode $str and it works as expected but the result is, of course, pretty much unreadable.
However, for debugging & presentation reasons I would prefer an encoded/sanitised string that resembled the original dict value inasmuch as reasonable and used a character set that avoids spaces, quotes, etc.
So, I am looking for something like ::base64 mapping procs but with a lighter
touch.
Any suggestions would be appreciated.
You can make lighter-touch quoting schemes using either string map or regsub to do the main work.
Here's an example of string map:
set input "O'Donnell's Bait Shop"
set quoted '[string map {' {'\''}} $input]' ; #'# This comment just because of stupid Stack Overflow syntax highlighter
puts $quoted
# ==> 'O'\''Donnell'\''s Bait Shop'
Here's an example of regsub:
set input "This uses a hypothetical quoting of some letters"
set quoted <[regsub -all {[pqr]} $input {«&»}]>
puts $quoted
# ==> <This uses a hy«p»othetical «q»uoting of some lette«r»s>
You'll need to decide what sort of quoting you really want to use. For myself, if I was going through several shells, I'd be wanting to avoid quoting at all (because it is difficult to get right) and instead find ways to send the data in some other way, perhaps over a pipeline or in a temporary file. At a pinch, I'd use an environment variable, as shells tend to not mess around with those nearly as much as arguments.

Can we give array name with hyphen in TCL

I am declaring a array in TCL say
set JDSU-12-1(key) element
parray JDSU-12-1
I am getting error saying JDSU is not a array
Even simple puts statement is not working
% puts $JDSU-12-1(key)
can't read "JDSU": no such variable
Is there any way i can declare array name with hyphen. I know _ works in array but not sure about hyphen
You can use special characters in Tcl variable names. You need the braces for those though:
% puts ${JDSU-12-1(key)}
element
You can even use $:
% set \$word "Hello world" ;# Or set {$word} "Hello world"
% puts ${$word}
Hello world
EDIT: Some reference:
beedub.com (Emphasis mine)
The set command is used to assign a value to a variable. It takes two arguments: the first is the name of the variable and the second is the value. Variable names can be any length, and case is significant. In fact, you can use any character in a variable name.
You can use almost any character for the name of a variable in Tcl — the only restrictions relate to :: as that is a namespace separator, and ( as that is used for arrays — but the $ syntax is more restrictive; the name it accepts (without using the ${…} form) has to consist of just ASCII letters, ASCII digits, underscores or namespace separators. Dashes aren't on that list.
The standard (and simplest) way of reading from a variable with a “weird” name is to use set with only one argument, as that happily accepts any legal variable name at all:
puts "the element is '[set JDSU-12-1(key)]'"
However, if you're doing this a lot it is actually easier to make an alias to the (array) variable name:
upvar 0 JDSU-12-1 theArray
puts "the element is $theArray(key)"
That's exactly how parray does it, though it uses upvar 1 because it is aliasing to a variable in the calling scope and not in the current scope.
Although you can use such special characters, you can only use a few when you try to access variables with $varname.
To quote the relevant section from the manual:
$name
Name is the name of a scalar variable; the name is a sequence of one or more characters that are a letter, digit, underscore, or namespace separators (two or more colons). Letters and digits are only the standard ASCII ones (0-9, A-Z and a-z).
$name(index)
Name gives the name of an array variable and index gives the name of an element within that array. Name must contain only letters, digits, underscores, and namespace separators, and may be an empty string. Letters and digits are only the standard ASCII ones (0-9, A-Z and a-z). Command substitutions, variable substitutions, and backslash substitutions are performed on the characters of index.
${name}
Name is the name of a scalar variable or array element. It may contain any characters whatsoever except for close braces. It indicates an array element if name is in the form “arrayName(index)” where arrayName does not contain any open parenthesis characters, “(”, or close brace characters, “}”, and index can be any sequence of characters except for close brace characters. No further substitutions are performed during the parsing of name.
There may be any number of variable substitutions in a single word. Variable substitution is not performed on words enclosed in braces.
Note that variables may contain character sequences other than those listed above, but in that case other mechanisms must be used to access them (e.g., via the set command's single-argument form).
I want to empathis the last paragraph a bit:
You are always able to read any variable with set varname:
set JDSU-12-1(key) element
puts [set JDSU-12-1(key)]
Unlike the ${varname} access, you can substitute a part of the variable name (in your case the array key), the entire variable, while set k "key"; puts ${JDSU-12-1($k)} does not work.
You can easily do that:
set set-var "test"
while accessing so ${set-var}
Like in most other programming languages, TCL variable must be alphanumeric starting with letter (A to Z, or _). Hyphen or dash (-) is not permitted as part of variable name, otherwise it would be confused with arithmetic minus or subtraction: there would be no difference between $x-1 as variable with name "x-1" or $x-1 as variable x minus 1.
Try this :)
subst $\{[subst ${conn}](phan)\}
Which version are you working ??
my tcl works.
% set JDSU-12-1(key) element
element
% parray JDSU-12-1
JDSU-12-1(key) = element

TCL: How to create and use variable with names containing curly braces?

Some variable names in my program are constructed from inputs of user so they may contain any symbols. Some symbols are treated as special by interpreter e.g. $,#, .... The problems concerning that symbols were solved by adding open brace on the beginning of constructed variable name and close brace at the end of it. But now another problem arises when the name of variable contains curly closing brace.
set "a{}" text
puts $a{}
puts ${a{}}
None of tow puts work here. How can I print the value of variable a{} and is there any known method for dealing with special symbols in TCL?
From the manual:
Note that variables may contain character sequences other than those listed above, but in that case other mechanisms must be used to access them (e.g., via the set command's single-argument form).
Use set
puts [set "a{}"]
the $ way is restricted, set is not

TCL set Special Characters in a string

I want to set in TCL the below error message as a variable and compare with the error message from a network switch, by-passing the special characters
Use [slot/port] or ["portname"] or [slot/*] or [*].
I tried in this way
set x "Use \[slot/port] or \["portname"] or \[slot/\*] or \[\*]."
but I am getting the following message while running my script:
extra characters after close-quote
while executing
Please help. Thank you!
If you use double quotes, you also have to escape "inner" quotes:
set x "Use \[slot/port] or \[\"portname\"] or \[slot/*] or \[*]."
Or use braces and avoid escaping altogether
set x {Use [slot/port] or ["portname"] or [slot/*] or [*].}
See Tcl's 12 syntax rules, numbers 4 and 6
Well, you can use wrap it in curly brackets as follows:
set x {Use [slot/port] or ["portname"] or [slot/] or [].}
Alternatively, you can escape special characters with backslash.
Escape the double quotes in your quoted string as well. Or use curly-braces to group the string without any command or variable substitution occurring.
set s {Use [slot/port] or ["portname"] or [slot/*] or [*].}
puts $s
set s "Use \[slot/port\] or \[\"portname\"\] or \[slot/*\] or \[*\]."
puts $s
You need to keep reading the documentation on quoting until you understand why this is ok and your example is broken or you will suffer endless problems in your scripting.
Note that the code colouring implemented on stackoverflow will show the curly-braced version poorly. Tcl is quite content with this however.

Comment syntax history

In early Tcl versions, was the comment command (#anything) treated exactly as a normal command (parsed) with the only exception that the arguments weren't sent anywhere? So you could do this...
% # {
comment
}
...but not this:
% # remember to initialize $width here
can't read "width": no such variable
% # a comment [with brackets] here
invalid command name "with"
In what version(s) did it change to completely ignore everything after the # character to the end of line?
The oldest released version of Tcl on sourceforge is 2.1. From the manpage in that tarball:
COMMENTS
If the first non-blank character in a command is #, then everything
from the # up through the next newline character is treated as
a comment and ignored.
So; no, for all practical purposes, comments are and have always been special syntax, not a regular tcl command.
Edit, re some comments (meta-comments?)
one of the reasons why comments aren't regular commands is because it provides an easy out for matching curly braces when you don't want them to match. Suppose you wanted to write a proc that prints a single close brace.
proc writeBrace {} {
puts "}"
}
unfortunately, the braces are no longer matched, and tcl sees, as the body of the proc puts ", since thats whats between the open brace and the matching close brace. the fix is easy:
proc writeBrace {} {
# match the brace below: {
puts "}"
}
now, the number of open and close braces is matched in the proc body. remember, braces are matched before tcl tries to parse a proc body, it's just a string during argument parsing, not tcl code.
The rules do not state that every character after # is ignored, its a little bit more tricky than that.
This page on the Tcl'ers wiki explains the pitfalls of comment syntax in depth, so i won't repeat all of this here:
http://wiki.tcl.tk/462
Basically its an order of evaluation issue, the braces are used for grouping first, before the commands are looked at.