how to use lsearch in tcl with numeric - tcl

I am new to TCL word. I have a list which js numeric and when I use lsearch for numeric it is not print properly. Could you please help me what's wrong in my command
set a {12,121,124,21,212}
lsearch -integer $a 12
Expected output : 12
Actual Output : 12,121, 124, 212

You've got a list that is separated by commas, whereas Tcl lists (the kind that lsearch can search and lsort can sort) are separated by spaces. The split command can do the conversion for you:
set a {12,121,124,21,212}
set theList [split $a ","]
lsearch -integer $theList 12
The result of the search is 0, which is the index of the first item in the list (Tcl uses zero-indexing, like a lot of programming languages).
To get the actual value found (no so useful in this case, but definitely more useful in more complex ones) you'd provide the -inline option.
lsearch -inline -integer $theList 12

Related

How to search for 0,a1[4],* where * is a wildcard in a list of 0,a2,4 0,a1[4],3 0,a1[4],5 .... in tcl

I tried lsearch -all $list_ 0,a1[4],*
a1[4] is stored in a variable
SO basically need
set var "a1[4]"
lsearch -all $list_ 0,$var,*
By default lsearch uses glob patterns (as described by the documentation for string match — it's the exact same matching engine being used). That's good because it means that * is a wildcard, but awkward because it means that [ is also special (it starts a character set match). You need some simple escaping, and to keep that sane you should put your whole pattern in {braces} so we don't need to fight with Tcl over what the meanings of bracket and backslash are:
lsearch -all $list_ {0,a1\[4\],*}
You don't need braces; you could write this instead:
lsearch -all $list_ 0,a1\\\[4\\\],*
But that's ugly! And difficult to maintain (trust me on that). So use braces, OK?
In the case where you're pulling the subpattern from a variable, things get more complicated. The fix is to use string map (or regsub) to condition the pattern piece.
# Split into three lines for clarity; qvar = “quoted var”
set ADD_BACKSLASHES {[ {\[} ] {\]}}
set qvar [string map $ADD_BACKSLASHES $var]
lsearch -all $list_ 0,$qvar,*

How to get the entire string from from particular index in TCL

I want 10576.53012.46344.35174 from string
"CompositionClassification|CC000003|01|10576.53012.46344.35174"
I have index of last occurrence of |, how will i get complete 10576.53012.46344.35174 sub-string from last |
Not familiar with TCL, Suggest solution on this :)
If you know the index of the first character you want, and you want from there to the end, you use:
set theSubstring [string range $theString $idx end]
However in this case I'd use split and lindex, since it looks like a simple delimited list:
set theSubstring [lindex [split $theString "|"] end]

tcl lsearch can't get something like this a\[1\]

I have a lsearch issue.
here is my code.
set aa 11
lappend aa a\[1\]
lsearch $aa a\[1\]
why doesn't it work?
Try:
lsearch -exact $aa a\[1\]
By default lsearch uses glob-style matching. The backslashes prevent [1] being treated as a command substitution, but then lsearch sees the item to find as a[1] which as a glob pattern just means "a" followed by "1". So you need the -exact flag to have the item to find just treated as literal text.

regular expression to treat unbalanced braces as a word

I am getting an error message in this regex when line contains unbalanced braces.
set line "a b { c{}"
set lst [regexp -all -inline {^(\s*(\S*)\s*)*(\{(.*)\})?(\s*(\S*)\s*)*$} $line]
set lst [lindex $lst 0]
set firstelement [lindex $lst 0]
How to avoid such cases and treat unbalanced braces as a word?
When you have a string from an arbitrary source (like a user) there's no guarantee at all that it is a well-formed list. Now regexp -inline returns a list of what it matched, but the elements of that list are strings (unless you use the -indices option, of course) and that means that you can't safely use lindex on them to pick out the pieces.
The safe way to get the first “word”, assuming you define “word” to be “sequence of non-whitespace characters” (the usual user definition), is to do this:
set firstWord [lindex [regexp -all -inline {\S+} $item] 0]
It's a bit ugly, but it's totally safe. (In fact, for the first word only, use regexp -inline {\S+} $item on its own, but that won't let you get later words.)
Using split to break a string into words is also possible, but that strongly assumes that the word separator is a single (whitespace-by-default) character and does something that you might not expect if you have multi-whitespace separators, or leading and trailing whitespace. Frankly, it's more useful for dividing up non-whitespace separated strings (e.g., a file into lines, an /etc/passwd record into fields) or for turning a string into the list of its characters (with an empty second argument).
The regexp command returns a list. You then take the first element of the list. But in the final line you then treat that element as a list - but it is not guaranteed to be so - hence the actual string content matters. Instead, if you want to deal with this item as a list you need to use split and convert it into words:
% split "a b {" " "
a b \{
In your case:
set lst [lindex $lst 0]
set firstelement [lindex [split $lst " "] 0]
You may also want to look into subst. It looks like you are trying to read poorly specified tcl lists as input and doing some parsing to get them as a proper tcl list. In which case, subst -nocommands [lindex $lst 0] might be more helpful to you. For example:
% lindex [subst -nocommands [lindex $lst 0]] 2
c{}
Note that this is the content of the braced part of $line.

list doesn't contain its own members in Tcl

I have a list containing one member, that member is the string <cmd_stichstudy1>XXDDR0_MA[12]. When I search for that string in the list (using lsearch) I get that the list doesn't contain it. I even get it when I search for the member of the list:
tcl> set nets_names
{<cmd_stichstudy1>XXDDR0_MA[12]}
tcl> lsearch $nets_names [lindex $nets_names 0]
-1
Why does this happen?
If you use -exact it will work the way you want.
% set nets_names {<cmd_stichstudy1>XXDDR0_MA[12]}
<cmd_stichstudy1>XXDDR0_MA[12]
% lsearch -exact $nets_names [lindex $nets_names 0]
0
%
lsearch has an unfortunate property of using glob-style matching by default.
To cite the manual:
If all matching style options are omitted, the default matching style is -glob.
So always pass -exact to lsearch unless you really want -glob.