I'm using the following expect(1) script to receive a list of users on a Teamspeak server using the Telnet Server Query.
#!/usr/bin/expect
# Spawn TELNET
spawn telnet example.com 10000
expect "TS3"
# Login
send "login $USER $PASS\r"
# Set serverID
send "use sid=$SSID\r"
expect "error id=0 msg=ok"
# Get clients
send "clientlist\r"
This produces an output like this:
clid=512 cid=3 client_database_id=4 client_nickname=User1 client_type=1|clid=486 cid=3 client_database_id=26 client_nickname=User2 client_type=0
Then, I can use the following code to get the client id (clid=*) of the first user;
# Get clients
send "clientlist\r"
expect -re "clid=(\\d+) "
set clid $expect_out(1,string)
puts "$clid"
# Output: 512
Questions:
for
/foreach
?I've tried to use the accepted answer in this question: How do I extract all matches with a Tcl regex?, however I'm so far unable to apply it on the output of a send
, instead of a variable
There are many ways to handle this, but the most natural might be to go by these steps: first, instead of separate expect
and set
lines, use the facility of doing the set
as result of a match:
expect -re "clid=(\\d+) " { set clid $expect_out(1,string) }
puts "$clid"
This is slightly better as clid
will only be set if the pattern matches.
The next step is then to use the command exp_continue
to restart the matching process. It is like a for
loop. See man expect
.
expect -re "clid=(\\d+) " {
set clid $expect_out(1,string)
puts "$clid"
exp_continue
}
To make clid
into a list (which in tcl is really just a string), use the list commands:
expect -re "clid=(\\d+) " {
lappend clid $expect_out(1,string)
exp_continue
}
puts "$clid"
Now you can iterate through the list with
foreach id $clid { puts $id }
You should now think about how to detect the end of the output of the clientlist
command, so that you can match it instead of stopping due to a timeout.
(Post a new question if blocked in your progress).