Iteration in TCL using for each - for-loop

I'm trying to iterate the value using for each in TCL
This how i give input
./a.sh value1,value2
in the a.sh script
set var [lindex $argv 0]
set values [split $var ","]
foreach {set i 0} {$values} {
puts "iterated once $i"
}
i want the iteration to happen twice since there are two values passed . but instead it is iterating only once
please help me on this
thanks in advance

The foreach command, in its simplest form, takes a variable name, a list value, and a script to run for each element of the list. What you were passing was… weird in several ways at once. Look, here's a correct way of doing it:
set values [split $var ","]
foreach item $values {
puts "iterated: $item"
}
If you want to count through, you should set up your own counter:
set values [split $var ","]
foreach item $values {
set i [incr counter]
puts "iterated #$i: $item"
}
That can be shortened to this:
foreach item [split $var ","] {
puts "iterated #[incr counter]: $item"
}

Related

tcl insert string at certain line in file

I want to insert one string at the certain line ,and I know the line number.
ex.
#Aa_version = Aa/45.21-a32_1
#Aa_version = Aa/47.21-a33_1
Aa_version = Aa/45.27-a57_2 ->I can get this line number n
and I want to insert one line Aa/49.27-a54_1 at line n+1
and put Aa_version = Aa/45.27-a57_2 -> #Aa_version = Aa/45.27-a57_2
output is like
#Aa_version = Aa/45.21-a32_1
#Aa_version = Aa/47.21-a33_1
#Aa_version = Aa/45.27-a57_2
Aa_version = Aa/49.27-a54_1
and my code is
set Aa ""
set fp [open $file "r+"]
set lines [split [read $fp] \n]
set idx [lsearch -regexp $lines {^Aa_version} ]
regexp {Aa(.+)} [lindex $lines $idx] Aa_version
set old_version "#$Aa_version"
set newAa [gets stdin]
set new_version "Aa_version =$newAa "
puts $old_version ->replace $Aa_version
puts $new_version
close $fp
How can I put them at the correct line
thanks
I think it's easier and cleaner to handle the input file a line at a time and look at each one in turn instead of reading it all in one single go and then finding, altering and inserting elements in a list:
set fp [open $file]
while {[gets $fp line] >= 0} {
# If the line starts with Aa_version...
if {[string match "Aa_version*" $line]} {
# Comment it out
puts "#$line"
# And read the new version and write it out
set newAa [gets stdin]
puts "Aa_version = $newAa"
# Copy the rest of the file to standard output and exit the loop
chan copy $fp stdout
break
} else {
puts $line
}
}
close $fp
But if you want to keep the current list based approach, lreplace is your friend:
set fp [open $file]
set lines [split [read $fp] \n]
close $fp
set idx [lsearch -glob $lines "Aa_version*"]
# If a match was found...
if {$idx >= 0} {
# Read the new verson
set newAa [gets stdin]
# Replace the version element with two new elements:
# Commented out previous version, and new version
set lines [lreplace $lines $idx $idx \
"#[lindex $lines $idx]" "Aa_version = $newAa"]
}
puts [join $lines \n]

wrong # args: should be "foreach varList list ?varList list ...? command"

this is the .txt file
desk-12
desk-123
desk-auto-1234
this is the .expect file
#!/usr/bin/expect
set f [open "listOfIps.txt"]
set ips [split [read $f] "\n"]
close $f
set PASSWORD "test#123"
puts "$ips"
foreach HOST $ips{
expect -> "
puts $HOST
#spawn scp -r /usr/bin/scp /Users/test-123/1.png admin#$HOST:/home/testFolder
expect {
"*password:*"
{ send $PASSWORD\r}
}
}
puts "completed"
can anyone help me how to solve this "wrong # args: should be "foreach varList list ?varList list ...? command"" error
On the line
foreach HOST $ips{
you need to add a space between $ips and { for Tcl to parse this correctly.

Expect loop doesn't print variables

I can't get to have the variables in an expect loop written:
#!/bin/bash
expect -c "
set var1 10
puts {$var1}
puts $expect_out({$var1})
foreach name { bob jim jacobo henric } {
puts {hello $name $var1}
}"
my output is:
# ./test
({})
hello
hello
hello
hello
So basically it's not expanding any variable.
Any idea?
You should quote with ', not "! This should get the job done:
#!/bin/bash
expect -c '
set var1 10
puts "$var1"
send_user "Confirm? (Y/n): "
expect_user -re "(.*)\n"
set var1 $expect_out(1,string)
foreach name { bob jim jacobo henric } {
puts "hello $name $var1"
}
'
Output:
10
Confirm? (Y/n): Y
hello bob Y
hello jim Y
hello jacobo Y
hello henric Y
Thanks a lot, it worked as a charm.
But it has some issues when the array elements are passed via parameter like this:
function a {
names=$1
expect -c '
foreach name { $names } {
puts "$name"
}
'
}
It just prints:
$names
you mean that any variable must be wrap around by single and double quotes?
' "$variable" '
ok I decided to put the expect code in a separate script test.ex:
set interfaces [lindex $argv 0]
foreach int { $var} {
puts $int
}
When I call the expect it does not cycle over the strings elements:
test.ex "string1 string2"
as it just prints:
$var
It is just ignoring the variable content, and it handles the variable as a string itself without expanding it, is there a way to get it work?
I figured it out!
Just needed to remove the curly brackets {} around the variable that need to be looped over:
set interfaces [lindex $argv 0]
foreach int $var {
puts $int
}

need tcl progam for sorting (without lsort)

I Need tcl programm for sorting, but i should not use lsort operation.
i have tried this. but no luck
set list1 {1 6 5 4}
set list2 {}
for {set i 0} {$i < [llength $list1]} {incr i} {
set temp [lindex $list1 $i]
for {set z [expr $i+1]} {$z < [llength $list1]} {incr z} {
set temp2 [lindex $list1 $z]
#puts "$temp,$temp2,$list1,$i,$z"
#puts $temp2
if {$temp < $temp2} {
} else {
puts "$i,$z"
set list1 [lreplace $list1 $i $i $temp2]
puts "> $list1"
set list1 [lreplace $list1 $z $z $temp]
puts ":: $list1"
}
}
}
puts $list1
Thanks
Ranjith
Well, you can implement all sorts of sorting algorithms if you want. Just treat Tcl's lists like an array in any number of other languages:
Create with lrepeat if necessary, though with a sorting algorithm you're usually given the list to sort.
Read the value at a particular index with lindex.
Write the value at a particular index with lset.
As a hint, here is how to swap the elements at two indices, $i and $j. It uses a temporary variable, tmp:
set tmp [lindex $list1 $i]
lset list1 $i [lindex $list1 $j]
lset list1 $j $tmp

How to store a line from expect_out(buffer) to a variable in tcl

For example, if the output ( in expect_out(buffer) )is
blah
blh blah
asdjsudfsdf
how can I store the 2nd line to a variable? so far I have this:
foreach line [split $expect_out(buffer) "\n"] {
if [lindex $line 1] {
set variable $line
}
}
But this does not work, it says the variable variable is undefined. I tried adding a counter, but that didn't work either. There has to be an easier way!
yes there is an easier way:
set lines [split $expect_out(buffer) \n]
set variable [lindex $lines 1]
or in one line
set variable [lindex [split $expect_out(buffer) \n] 1]
Keep mindful you know what Tcl commands return: split returns a list. You then use lindex to find the 2nd element of the list.

Resources