http://www.purl.org/tcl/home/man/tcl8.4/TclCmd/lsearch.htm
The simplest invocation form for lsearch is:
lsearch list search_term
lsearch searches the first argument list for an element that matches the search_term argument.
caspian: lsearch returns -1 if search_term was not found.
Suppose you have this list:
set yourlist {RedHat SUSE Debian Knoppix Peanut Mandrake Slackware}
...and you run lsearch to check if a given Linux distribution is present in the list. If it is, it will return the index, i.e. its position in the list.
lsearch $yourlist RedHat
...would return 0 (zero) because the count starts from zero and "RedHat" is the first item in the list. "SUSE" would return 1 (one) and "Slackware" would return 6 (six).
If the item is not present in the list, the search returns -1 (minus one), so in order to check the presence of an item in the list, we can just check if the return value is a positive number, i.e. greater than zero or zero:
if { [ lsearch $yourlist Debian ] >= 0 } { puts "Debian is in the list" } else { puts "There is no Debian in the list" }
"RedHat" can be a tricky string to search because it is mixed case, so scroll down this page to see how we can run a case-insensitive search within a list. It involves using regular expressions in the search string.
If you get to use regular expressions, -inline becomes a very useful switch. It makes lsearch return the element found instead of its index. Or, instead of regular expressions, we can use a simple glob pattern. Run...
lsearch -inline $yourlist *ware
... and get Slackware instead of a relatively meaningless integer, i.e. the list index.
But note that all searches above will return the first element found. If you want to find all matches, use the -all switch:
lsearch -all $yourlist *an*
...returns the list {2 4 5}: Debian, Peanut and Mandrake.
Combine -all with -inline and get all names instead of all indices:
lsearch -all -inline $yourlist *an*
... returns the list {Debian Peanut Mandrake}
The default for lsearch is -glob . However, be certain the glob behavior is what you expect.
For instance, check out this code.
set a [list field1:val1=field3 field2:val2=2 field3:val3=3 field3] set b [lsearch $a field3] puts $b
Would you expect glob to mean that element 0, 2, or 3 would be returned? 3 is the answer you get. On the other hand,
set b [lsearch -regexp $a field3] puts $b
returns 0.
Case-insensitive lsearch: Use (?i) in the -regexp for case-insensitive comparison:
% lsearch -regexp {Foo Bar Grill} {(?i)BAR} 1
From Tcl 8.4, fancy new modes have been added: -all gives you all instances (instead of the first only); -inline gives the elements themselves instead of their index. So a very easy filter that removes empty sublists from a list is
lsearch -all -inline $list ?* ;# RS - example: % lsearch -all -inline {foo {} bar {} grill} ?* foo bar grill
From 8.5 on there will be even more switches, for example TIP127 -index option.
See also list, lappend, lindex, linsert, llength, lrange, lreplace, lsort . Recursive list searching gives you an index vector which can be used with lindex/lset.
Tcl syntax help - Arts and crafts of Tcl-Tk programming - Category Command