How to get the entire string from from particular index in TCL - 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]

Related

how to use lsearch in tcl with numeric

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

Split camelcase value with TCL

I have this TCL expression:
[string toupper [join [lrange [file split [value [topnode].file]] 1 1]]]
This retrieves companyName value from c:/companyName... and I need to split that value before the first capital letter into Company Name. Any ideas?
Thanks in advance.
That's rather more in one word than I would consider a good idea. It makes the whole thing quite opaque! Let's split it up.
Firstly, I would expect the base company name to be better retrieved with lindex from the split filename.
set companyName [lindex [file split [value [topnode].file]] 1]
Now, we need to process that to get the human-readable version out of it. Alas, that's going be a bit difficult without knowing what's been done to it, but if we use as our example fooBarBoo_grill then we can see what we can do. First, we get the pieces with some regular expressions (this part might need tweaking if there are non-ASCII characters involved, or if certain critical characters need special treatment):
# set companyName "fooBarBoo_grill"
set pieces [regexp -all -inline {[a-z]+|[A-Z][a-z]*} $companyName]
# pieces = foo Bar Boo grill
Next, we need to capitalise. I'll assume you're using Tcl 8.6 and so have lmap as it is perfect for this task. The string totitle command has been around for a very long time.
set pieces [lmap word $pieces {string totitle $word}]
# pieces = Foo Bar Boo Grill
That list might need a bit more tweaking, or it might be OK as it is. An example of tweaking that might be necessary is if you've got an Irish name like O'Hanrahan, or if you need to insert a comma before and period after Inc.
Finally, we properly ought to set companyName [join $pieces] to get back a true string, but that doesn't have a noticeable effect with a list of words made purely out of letters. Also, more complex joins with regular expressions might be needed if you've done insertion of prefixing punctuation (the , Inc. case).
If I was doing this for real, I'd try to have the proper company name expressed directly elsewhere rather than relying on the filename. Much simpler to get right!
To begin with, try using
lindex [file split [value [topnode].file]] 1
The lrange command will return a list, which might cause problems with some directory names. The join command should be pointless if you don't use lrange, and string toupper removes the information you need to do the operation you want to do.
To split before uppercase letters, you can use repetitive matches of either (?:[a-z]+|[A-Z][a-z]+) (ASCII / English alphabet letters only) or (?:[[:lower:]]+|[[:upper:]][[:lower:]]+) (any Unicode letters).
% regexp -all -inline {(?:[a-z]+|[A-Z][a-z]+)} camelCaseWord
camel Case Word
Use string totitle to change the first letter of the first word to upper case.
Documentation:
file,
lindex,
regexp,
string,
Syntax of Tcl regular expressions

How to append two string in TCL with a space between them?

I'm trying to append two string in tcl. I'm reading from csv and set values to the variables and then i will use that for assigning it my application. I tried the below one.
set vMyvalue [lindex $lsLine 17]
append vMyvalue " [lindex $lsLine 18]"
it is giving me the expected result. Like for e.g if i have values 250 and km in 17th and 18th position in csv. i'm getting
250 km
But the problem is when there are no values in the 17th and 18th i mean when it is empty, that time also it is adding space. But my application won't allow me to assign space for that value. How can i resolve this? I just started working in TCL. I'm not aware of many functions.
I think the most intuitive way to handle cases similar to this one if you don't know a function to do this (including for example if you are joining two strings with some character but if any one of them are empty strings, then you want something different to be done), would be to use if. In this case:
if {$vMyvalue eq " "} {set vMyvalue ""}
If you want to make your code somewhat shorter, you can make use of the functions lrange (list range), join and string:
set vMyvalue [string trim [join [lrange $lsLine 17 18] " "]]
lrange returns a list of elements from the list $lsLine between indices 17 to 18 inclusive, then join literally joins those elements with a space, and last, string trim cleans up any leading and trailing spaces (removing the space completely if it is the only character in the string).
There are several ways to do this. The minimum modification from the code you already have is probably to trim the result. Trim removes leading and trailing whitespace but if it's only whitespace it would trim it to an empty string. So:
set myValue [string trim $myValue]

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.

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.