Tcl
— Kaushal ModiNotes as I am learning Tcl syntax using its official tutorial.
tclsh
version- Simple Text Output
- Assigning values to variables
- Evaluation & Substitutions 1: Grouping arguments with
""
- Evaluation & Substitutions 2: Grouping arguments with
{}
- Evaluation & Substitutions 3: Grouping arguments with
[]
- Results of a command - Math 101
- Computers and Numbers
- Numeric Comparisons 101 -
if
- TODO Textual Comparison -
switch
- Looping 101 -
while
loop - Looping 102 -
for
andincr
- Adding new commands to Tcl -
proc
- Variations in
proc
arguments and return values - TODO Variable scope -
global
andupvar
- Tcl Data Structures 101 - The list
- TODO Adding & Deleting members of a list
- TODO More list commands - lsearch, lsort, lrange
- TODO Simple pattern matching - “globbing”
- TODO String Subcommands - length index range
- TODO String comparisons - compare match first last wordend
- TODO Modifying Strings - tolower, toupper, trim, format
- Regular Expressions 101
- TODO More Examples Of Regular Expressions
- TODO More Quoting Hell - Regular Expressions 102
- TODO Associative Arrays
- TODO More On Arrays - Iterating and use in procedures
- TODO Dictionaries
- TODO File Access 101
- TODO Information about Files - file, glob
- TODO Invoking Subprocesses from Tcl - exec, open
- TODO Learning the existence of commands and variables ? - info
- TODO State of the interpreter - info
- TODO Information about procs - info
- TODO Modularization - source
- TODO Building reusable libraries - packages and namespaces
- TODO Creating Commands - eval
- TODO More command construction - format, list
- TODO Substitution without evaluation - format, subst
- TODO Changing Working Directory - cd, pwd
- TODO Debugging & Errors - errorInfo errorCode catch error return
- TODO More Debugging - trace
- Command line arguments and environment strings
- TODO Leftovers - time, unset
- TODO Channel I/O: socket, fileevent, vwait
- TODO Time and Date - clock
- TODO More channel I/O - fblocked & fconfigure
- TODO Child interpreters
- Miscellaneous
- Reference
tclsh
version #
puts $tcl_version
8.6
Simple Text Output #
If a string has more than one word (i.e. has space), it must be enclosed in
" "
or{ }
.puts "Hello, World - In Double Quotes" puts {Hello, World - In Braces}
Note that single quotes have no significance in Tcl.
Hello, World - In Double Quotes Hello, World - In Braces
If the string has no space, the quotes or braces are not needed.
puts Hello
Hello
This is how you normally type a comment
# This is a comment at beginning of a line
A Tcl command is terminated by a newline or a semicolon.
puts "This is line 1" puts "this is line 2" puts "This is line 3"; puts "this is line 4" puts "Hello, World; - With a semicolon inside the quotes"
This is line 1 this is line 2 This is line 3 this is line 4 Hello, World; - With a semicolon inside the quotes
The same “semicolon ends a command” applies when ending a command and starting a comment on the same line.
puts "Hello, World - In quotes" ;# This is a comment after the command.
Hello, World - In quotes
Below will not work as there is no semicolon separating the command and the comment.
puts {Bad comment syntax example} # *Error* - there is no semicolon!
Assigning values to variables #
set
assigns a value to a variable and then also returns the same.
set fruit Cauliflower
Cauliflower
set X "This is a string"
set Y 1.24
puts $X
puts $Y
puts "..............................."
set label "The value in Y is: "
puts "$label $Y"
This is a string
1.24
...............................
The value in Y is: 1.24
The dollar sign tells Tcl to use the value of the variable - in this
case X
or Y
.
Evaluation & Substitutions 1: Grouping arguments with ""
#
Grouping words within double quotes allows substitutions to occur within the quotations - or, in fancier terms, “interpolation”. The substituted group is then evaluated as a single argument.
In general, the backslash (\
) disables substitution for the single
character immediately following the backslash. Any character
immediately following the backslash will stand without substitution.
However, there are specific “Backslash Sequence” strings which are replaced by specific values during the substitution phase.
puts "abc\n\tdef \u0A95"
abc
def ક
set Z Albany
set Z_LABEL "The Capital of New York is: "
puts "$Z_LABEL $Z" ;# Prints the value of Z
puts "$Z_LABEL \$Z" ;# Prints a literal $Z instead of the value of Z
puts "\nBen Franklin is on the \$100.00 bill"
set a 100.00
puts "Washington is not on the $a bill" ;# This is not what you want
puts "Lincoln is not on the $$a bill" ;# This is OK
puts "Hamilton is not on the \$a bill" ;# This is not what you want
puts "Ben Franklin is on the \$$a bill" ;# But, this is OK
puts "\n................. examples of escape strings"
puts "Tab\tTab\tTab"
puts "This string prints out \non two lines"
puts "This string comes out\
on a single line"
The Capital of New York is: Albany
The Capital of New York is: $Z
Ben Franklin is on the $100.00 bill
Washington is not on the 100.00 bill
Lincoln is not on the $100.00 bill
Hamilton is not on the $a bill
Ben Franklin is on the $100.00 bill
................. examples of escape strings
Tab Tab Tab
This string prints out
on two lines
This string comes out on a single line
Evaluation & Substitutions 2: Grouping arguments with {}
#
In contrast to words grouped in double quotes, no substitution happens in words grouped in curly braces.
set Z Albany
set Z_LABEL "The Capital of New York is: "
puts "\n................. examples of differences between \" and \{"
puts "grouped in double quotes: $Z_LABEL $Z"
puts {grouped in braces: $Z_LABEL $Z}
puts "\n....... examples of differences in nesting \{ and \" "
puts "braces in double quotes: $Z_LABEL {$Z}"
puts {double quotes in braces: Who said, "What this country needs is a good $0.05 cigar!"?}
puts "\n................. examples of escape strings"
puts {There are no substitutions done within braces \n \r \x0a \f \v}
puts {But, the escaped newline at the end of a\
string is still evaluated as a space}
................. examples of differences between " and {
grouped in double quotes: The Capital of New York is: Albany
grouped in braces: $Z_LABEL $Z
....... examples of differences in nesting { and "
braces in double quotes: The Capital of New York is: {Albany}
double quotes in braces: Who said, "What this country needs is a good $0.05 cigar!"?
................. examples of escape strings
There are no substitutions done within braces \n \r \x0a \f \v
But, the escaped newline at the end of a string is still evaluated as a space
Evaluation & Substitutions 3: Grouping arguments with []
#
You obtain the results of a command by placing the command in square
brackets ([]
). This is the functional equivalent of the back single
quote (`
) in shell scripting.
As the Tcl interpreter reads in a line it replaces all the $variables with their values. If a portion of the string is grouped with square brackets, then the string within the square brackets is evaluated as a command by the interpreter, and the result of the command replaces the square bracketed string.
Except ..
- A square bracket that is escaped with a
\
is considered as a literal square bracket. - A square bracket within braces is not modified during the substitution phase.
set x abc
puts "A simple substitution: $x\n"
set y [set x "def"]
puts "Remember that set returns the new value of the variable: X: $x Y: $y\n"
set z {[set x "This is a string within quotes within square brackets withing braces"]}
puts "Note that the curly braces prevented evaluation of the string in square brackets: $z\n"
set a "[set x {This is a string within braces within square brackets within double quotes}]"
puts "See how the set is executed: $a"
puts "\$x is: $x\n"
set b "\[set y {This is a string within braces beginning with an escaped square bracket within quotes}]"
# Note the \ escapes the bracket, and must be doubled to be a
# literal character in double quotes
puts "Note the \\ escapes the bracket:\n \$b is: $b"
puts "\$y is still \"$y\" from the first assignment"
A simple substitution: abc
Remember that set returns the new value of the variable: X: def Y: def
Note that the curly braces prevented evaluation of the string in square brackets: [set x "This is a string within quotes within square brackets withing braces"]
See how the set is executed: This is a string within braces within square brackets within double quotes
$x is: This is a string within braces within square brackets within double quotes
Note the \ escapes the bracket:
$b is: [set y {This is a string within braces beginning with an escaped square bracket within quotes}]
$y is still "def" from the first assignment
Results of a command - Math 101 #
The Tcl command for doing math type operations is expr
.
It’s recommended to enclose expr
arguments in curly braces – It is
faster, and also more secure. So do expr {$i * 10}
instead of simply
expr $i * 10
.
The expr
command performs its own round of substitutions on
variables and commands, so you should use braces to prevent the Tcl
interpreter doing this as well (leading to double substitution). In
the below example, the puts
in $userinput
is evaluated when
evaluating expr
, which very well might be unintended.
set userinput {[puts DANGER!]}
set foo [expr $userinput == 1]
puts $foo
DANGER!
0
Below as the expr
arguments are wrapped in { }
, the “DANGER!” is
avoided.
set userinput {[puts DANGER!]}
set foo [expr {$userinput == 1}]
puts $foo
0
TODO Operands #
Math Functions #
Tcl supports the following mathematical functions in expressions:
abs acos asin atan
atan2 bool ceil cos
cosh double entier exp
floor fmod hypot int
isqrt log log10 max
min pow rand round
sin sinh sqrt srand
tan tanh wide
set x 1
set w "Abcdef"
expr { [string length $w] - 2*$x }
4
Type Conversions #
Function | Description |
---|---|
double() | Convert to a float |
int() | Convert to an ordinary integer using truncation |
wide() | Convert to a “wide” integer number |
entier() | Coerses a number to an integer of appropriate size to hold it without truncation. |
set X 100
set Y 256
set Z [expr {$Y + $X}]
set Z_LABEL "$Y plus $X is "
puts "$Z_LABEL $Z"
puts "The square root of $Y is [expr { sqrt($Y) }]\n"
puts "Because of the precedence rules \"5 + -3 * 4\" is: [expr {-3 * 4 + 5}]"
puts "Because of the parentheses \"(5 + -3) * 4\" is: [expr {(5 + -3) * 4}]"
set A 3
set B 4
puts "The hypotenuse of a triangle: [expr {hypot($A,$B)}]"
#
# The trigonometric functions work with radians ...
#
set pi6 [expr {3.1415926/6.0}]
puts "The sine and cosine of pi/6: [expr {sin($pi6)}] [expr {cos($pi6)}]"
256 plus 100 is 356
The square root of 256 is 16.0
Because of the precedence rules "5 + -3 * 4" is: -7
Because of the parentheses "(5 + -3) * 4" is: 8
The hypotenuse of a triangle: 5.0
The sine and cosine of pi/6: 0.49999999226497965 0.8660254082502546
# Working with arrays
set a(1) 10
set a(2) 7
set a(3) 17
set b 2
puts "Sum: [expr {$a(1)+$a($b)}]"
Sum: 17
Computers and Numbers #
# Division
puts "1/2 is [expr {1/2}]"
puts "-1/2 is [expr {-1/2}]"
puts "1/2 is [expr {1./2}]"
puts "1/3 is [expr {1./3}]"
puts "1/3 is [expr {double(1)/3}]"
1/2 is 0
-1/2 is -1
1/2 is 0.5
1/3 is 0.3333333333333333
1/3 is 0.3333333333333333
set tcl_precision 17 ;# One of Tcl's few magic variables:
;# Show all decimals needed to exactly
;# reproduce a particular number
puts "1/2 is [expr {1./2}]"
puts "1/3 is [expr {1./3}]"
set a [expr {1.0/3.0}]
puts "3*(1/3) is [expr {3.0*$a}]"
set b [expr {10.0/3.0}]
puts "3*(10/3) is [expr {3.0*$b}]"
set c [expr {10.0/3.0}]
set d [expr {2.0/3.0}]
puts "(10.0/3.0) / (2.0/3.0) is [expr {$c/$d}]"
set e [expr {1.0/10.0}]
puts "1.2 / 0.1 is [expr {1.2/$e}]"
1/2 is 0.5
1/3 is 0.33333333333333331
3*(1/3) is 1.0
3*(10/3) is 10.0
(10.0/3.0) / (2.0/3.0) is 5.0000000000000009
1.2 / 0.1 is 11.999999999999998
Numeric Comparisons 101 - if
#
Put the if
test condition in curly braces.
set x 1
if {$x == 2} {puts "$x is 2"} else {puts "$x is not 2"}
if {$x != 1} {
puts "$x is != 1"
} else {
puts "$x is 1"
}
if $x==1 {puts "GOT 1"}
1 is not 2
1 is 1
GOT 1
set x 1
#
# Be careful, this is just an example
# Usually you should avoid such constructs,
# it is less than clear what is going on and it can be dangerous
#
set y x
if "$$y != 1" {
puts "$$y is != 1"
} else {
puts "$$y is 1"
}
#
# A dangerous example: due to the extra round of substitution,
# the script stops
#
set y {[exit]}
if "$$y != 1" {
puts "$$y is != 1"
} else {
puts "$$y is 1"
}
$x is 1
- For numbers, any non-zero value is a TRUE expression.
- For strings,
"yes"
and"true"
is a TRUE expression.
set str1 yes
if { $str1} { puts "yep" } else { puts "nope" }
set str2 true
if { $str2 } { puts "yep" } else { puts "nope" }
yep
yep
TODO Textual Comparison - switch
#
Looping 101 - while
loop #
In Tcl everything is a command, and everything goes through the same substitution phase. For this reason, the test must be placed within braces.
set x 1
while {$x < 5} { ;# Notice the while test enclosed in curly braces
puts "x is $x"
set x [expr {$x + 1}]
}
puts "exited first loop with X equal to $x"
x is 1
x is 2
x is 3
x is 4
exited first loop with X equal to 5
The next example shows the difference between ".."
and {..}
.
set x 0
while "$x < 5" { ;# This test is first evaluated and transformed to "0 < 5"
;# .. which will always be true!
set x [expr {$x + 1}]
if {$x > 7} break ;# This while loop would have run infinitely without this break
if "$x > 3" continue ;# the while loop short-circuts back to the top for x>3
puts "x is $x"
}
puts "exited second loop with X equal to $x"
x is 1
x is 2
x is 3
exited second loop with X equal to 8
Looping 102 - for
and incr
#
Put the for
test condition in curly braces.
When braces are used for grouping, the newline is not treated as the
end of a Tcl command. This makes it simpler to write multiple line
commands. However, the opening brace must be on the line with the
for
command.
for {set i 0} {$i < 4} {incr i} {
puts "I'm inside the first loop: $i"
}
for {set i 3} {$i < 2} {incr i} {
puts "I'm inside the second loop: $i"
}
I'm inside the first loop: 0
I'm inside the first loop: 1
I'm inside the first loop: 2
I'm inside the first loop: 3
Below, a while
loop is written similar to the first for
loop
above:
puts "Start"
set i 0
while {$i < 4} {
puts "I'm inside the while loop: $i"
incr i
puts "I'm after incr: $i"
}
Start
I'm inside the while loop: 0
I'm after incr: 1
I'm inside the while loop: 1
I'm after incr: 2
I'm inside the while loop: 2
I'm after incr: 3
I'm inside the while loop: 3
I'm after incr: 4
set i 0
incr i ;# now i is 1
# This is equivalent to:
set i [expr {$i + 1}] ;# now i is 2
incr i 3 ;# now i is 5
5
Adding new commands to Tcl - proc
#
In Tcl there is actually no distinction between commands (often known
as ‘functions’ in other languages) and “syntax”. There are no reserved
words (like if
and while
) as exist in C, Java, Python, Perl, etc.
So below works (but please don’t code like that!)!
set xxx set
$xxx foo if
$xxx bar puts
$xxx zoo else
$foo { true } { $bar "yep" } $zoo { $bar "nope" }
yep
proc sum {arg1 arg2} {
set x [expr {$arg1 + $arg2}]
return $x
}
puts " The sum of 2 + 3 is: [sum 2 3]"
The sum of 2 + 3 is: 5
In the below example, the original for
command has been destroyed to
do something else.
proc for {a b c} {
puts "The for command has been replaced by puts commands!"
puts "The arguments were:\n\t$a\n\t$b\n\t$c"
}
for {set i 1} {$i < 10} {incr i}
The for command has been replaced by puts commands!
The arguments were:
set i 1
$i < 10
incr i
Variations in proc
arguments and return values #
A proc can be defined with a set number of required arguments (as was
done with sum
in the previous section, or it can have a variable
number of arguments. An argument can also be defined to have a default
value.
Variables can be defined with a default value by placing the variable name and the default within braces within args. For example:
proc justdoit {a {b 1} {c -1}} {
puts "a = $a, b = $b, c = $c"
}
justdoit 10
justdoit 10 20
justdoit 10 20 30
a = 10, b = 1, c = -1
a = 10, b = 20, c = -1
a = 10, b = 20, c = 30
A proc will accept a variable number of arguments if the last declared
argument is the word args
.
proc example {first {second ""} args} {
if {$second eq ""} {
puts "There is only one argument and it is: $first"
return 1
} else {
if {$args eq ""} {
puts "There are two arguments - $first and $second"
return 2
} else {
puts "There are many arguments - $first, $second and $args"
return "many"
}
}
}
set count1 [example ONE]
set count2 [example ONE TWO]
set count3 [example ONE TWO THREE ]
set count4 [example ONE TWO THREE FOUR]
puts "The example was called with $count1, $count2, $count3, and $count4 Arguments"
There is only one argument and it is: ONE
There are two arguments - ONE and TWO
There are many arguments - ONE, TWO and THREE
There are many arguments - ONE, TWO and THREE FOUR
The example was called with 1, 2, many, and many Arguments
Using foreach
to loop through all the args of a proc:
proc my_proc {args} {
puts "Number of args = [llength $args]"
set idx 0
foreach arg $args {
puts " arg $list_idx = $arg"
incr idx
}
}
my_proc x
my_proc a b c d e f
Number of args = 1
arg 0 = x
Number of args = 6
arg 0 = a
arg 1 = b
arg 2 = c
arg 3 = d
arg 4 = e
arg 5 = f
TODO Variable scope - global
and upvar
#
Tcl Data Structures 101 - The list #
The list is the basic Tcl data structure. A list is simply an ordered collection of stuff; numbers, words, strings, or other lists.
set x "a b c" ;# Yes, Tcl interprets this string as a list too.
puts "Item at index 2 of the list {$x} is: [lindex $x 2]\n"
set i 0
foreach j $x {
puts "$j is item number $i in list x"
incr i
}
Item at index 2 of the list {a b c} is: c
a is item number 0 in list x
b is item number 1 in list x
c is item number 2 in list x
lindex lst idx
- Returns the item at
idx
index from thelst
list. Note that the list indices begin from 0. llength lst
- Returns the length of
lst
list.
set y [split 7/4/1776 "/"]
puts "We celebrate on the [lindex $y 1]'th day of the [lindex $y 0]'th month"
set z [list puts "arg 2 is $y" ]
puts "A command resembles: $z"
puts "Length of \$z list = [llength $z]"
eval $z
We celebrate on the 4'th day of the 7'th month
A command resembles: puts {arg 2 is 7 4 1776}
Length of $z list = 2
arg 2 is 7 4 1776
proc my_proc {args} {
puts "Number of args = [llength $args]"
for {set idx 0} {$list_idx < [llength $args]} {incr idx} {
puts " arg $list_idx = [lindex $args $list_idx]"
}
}
my_proc x
my_proc a b c d e f
Number of args = 1
arg 0 = x
Number of args = 6
arg 0 = a
arg 1 = b
arg 2 = c
arg 3 = d
arg 4 = e
arg 5 = f
foreach
can be used to take more than one variable at a time from a
list:
set x "a b c d e f"
foreach {var1 var2} $x {
puts "var1 = $var1, var2 = $var2"
}
foreach {var1 var2 var3} $x {
puts "var1 = $var1, var2 = $var2, var3 = $var3"
}
var1 = a, var2 = b
var1 = c, var2 = d
var1 = e, var2 = f
var1 = a, var2 = b, var3 = c
var1 = d, var2 = e, var3 = f
foreach
can even take a variable at a time from multiple lists:
set x "a b c"
set y "A B C"
set z "1 2 3"
foreach foo $x bar $y zoo $z {
puts "$foo $bar $zoo"
}
a A 1
b B 2
c C 3
TODO Adding & Deleting members of a list #
set b [list a b {c d e} {f {g h}}]
puts "Treated as a list: $b\n"
set b [split "a b {c d e} {f {g h}}"]
puts "Transformed by split: $b\n"
set a [concat a b {c d e} {f {g h}}]
puts "Concated: $a\n"
lappend a {ij K lm} ;# Note: {ij K lm} is a single element
puts "After lappending: $a\n"
set b [linsert $a 3 "1 2 3"] ;# "1 2 3" is a single element
puts "After linsert at position 3: $b\n"
set b [lreplace $b 3 5 "AA" "BB"]
puts "After lreplacing 3 positions with 2 values at position 3: $b\n"
Treated as a list: a b {c d e} {f {g h}}
Transformed by split: a b \{c d e\} \{f \{g h\}\}
Concated: a b c d e f {g h}
After lappending: a b c d e f {g h} {ij K lm}
After linsert at position 3: a b c {1 2 3} d e f {g h} {ij K lm}
After lreplacing 3 positions with 2 values at position 3: a b c AA BB f {g h} {ij K lm}
TODO More list commands - lsearch, lsort, lrange #
TODO Simple pattern matching - “globbing” #
TODO String Subcommands - length index range #
TODO String comparisons - compare match first last wordend #
TODO Modifying Strings - tolower, toupper, trim, format #
Regular Expressions 101 #
set sample "Where there is a will, There is a way."
#
# Only check if the match happened
#
set result [regexp {[a-z]+} $sample]
puts "Result: $result"
#
# Match the first substring with lowercase letters only, and save match to $match
#
set result [regexp {[a-z]+} $sample match]
puts "Result: $result match: $match"
#
# Match the first two words, the first one allows uppercase
set result [regexp {([A-Za-z]+) +([a-z]+)} $sample match sub1 sub2 ]
puts "Result: $result Match: $match 1: $sub1 2: $sub2"
#
# Replace a word
#
regsub "way" $sample "lawsuit" sample2
puts "New: $sample2"
#
# Use the -all option to count the number of "words"
#
puts "Number of words: [regexp -all {[^ ]+} $sample]"
Result: 1
Result: 1 match: here
Result: 1 Match: Where there 1: Where 2: there
New: Where there is a will, There is a lawsuit.
Number of words: 9
proc get_type {str} {
## Returns the string parsed between "_" and "_result_1234.log".
set result [regexp {_([a-z]+)_result_[0-9]+\.log} $str match sub1]
puts [format "%s -> match=%s, sub1=%s" $str $match $sub1]
return $sub1
}
puts [get_type "foo_test_bar_aaa_bar_result_123.log"]
puts [get_type "foo_test_bar_aaa_zoo_result_123.log"]
foo_test_bar_aaa_bar_result_123.log -> match=_bar_result_123.log, sub1=bar
bar
foo_test_bar_aaa_zoo_result_123.log -> match=_zoo_result_123.log, sub1=zoo
zoo
TODO More Examples Of Regular Expressions #
String replacement using regular expressions #
set str "foo1foo2foo3"
puts "str = $str"
set str [regsub -all foo $str bar]
puts "str = $str"
regsub -all bar $str zoo str
puts "str = $str"
set numMatches [regsub -all zoo $str tar str]
puts "str = $str, numMatches = $numMatches"
str = foo1foo2foo3
str = bar1bar2bar3
str = zoo1zoo2zoo3
str = tar1tar2tar3, numMatches = 3
Removing square brackets in strings #
set str "abc"
puts "str = $str"
set str {abc[1]}
puts "str = $str"
if {[string match *\\\[* $str]} {
puts yes
} else {
puts no
}
set str1 $str
puts "str1 = $str1"
str = abc
str = abc[1]
yes
str1 = abc[1]
TODO More Quoting Hell - Regular Expressions 102 #
TODO Associative Arrays #
TODO More On Arrays - Iterating and use in procedures #
TODO Dictionaries #
TODO File Access 101 #
TODO Information about Files - file, glob #
TODO Invoking Subprocesses from Tcl - exec, open #
TODO Learning the existence of commands and variables ? - info #
TODO State of the interpreter - info #
TODO Information about procs - info #
TODO Modularization - source #
TODO Building reusable libraries - packages and namespaces #
Below snippet shows that just declaring a variable
in a namespace
does not cause its info exists
status to become true – It needs to
be explicitly set
to a value.
namespace eval ::foo {
variable bar
}
puts [info exists ::foo::bar]
if {![info exists ::foo::bar]} { puts empty }
set ::foo::bar zoo
puts [info exists ::foo::bar]
0
empty
1
TODO Creating Commands - eval #
TODO More command construction - format, list #
TODO Substitution without evaluation - format, subst #
TODO Changing Working Directory - cd, pwd #
TODO Debugging & Errors - errorInfo errorCode catch error return #
TODO More Debugging - trace #
Command line arguments and environment strings #
- The number of command line arguments to a Tcl script is passed as
the global variable
argc
. - The name of a Tcl script is passed to the script as the global
variable
argv0
. - The rest of the command line arguments are passed as a list in
argv
.
puts "There are $argc arguments to this script"
puts "The name of this script is $argv0"
if {$argc > 0} {puts "The other arguments are: $argv" }
There are 0 arguments to this script
The name of this script is tclsh
Below outputs the full path of the executable that runs the Tcl
scripts; usually the path to tclsh
:
puts [info nameofexecutable]
Environment variables are available in Tcl via a global associative
array env
. The index into env
is the name of the environment
variable.
Below snippet dumps the names and values of all the set environment variables:
puts "You have these environment variables set:"
foreach index [array names env] {
puts "$index: $env($index)"
}
puts $env(EDITOR)
if {[info exists env(FOO)]} { ;# https://stackoverflow.com/a/7712763/1219634
puts "env var FOO is set"
} else {
puts "env var FOO is not set"
set env(FOO) abc
if {[info exists env(FOO)]} {
puts "Now env var FOO is set"
}
}
puts $env(FOO)
emacsclient
env var FOO is not set
Now env var FOO is set
abc
TODO Leftovers - time, unset #
TODO Channel I/O: socket, fileevent, vwait #
TODO Time and Date - clock #
TODO More channel I/O - fblocked & fconfigure #
TODO Child interpreters #
Miscellaneous #
Line continuation #
The tcl commands can continue onto the next line when the current line ends with a backslash.
puts "abc\
def"
set \
str\
"abc"
puts "str = $str"
abc def
str = abc
Setting array value #
array set colorcount {
red 1
green 5
blue 4
white 9
}
foreach {color count} [array get colorcount] {
puts "Color: $color Count: $count"
}
Color: blue Count: 4
Color: white Count: 9
Color: green Count: 5
Color: red Count: 1
Cycling through all elements in an array #
set idx 0
array set arr {
a
b
c
d
e
f
}
puts $list_idx
puts [array size arr]
foreach {el} [array get arr] {
puts "$el"
}
foreach {el1 el2} [array get arr] {
puts "$el1 $el2"
}
0
3
e
f
a
b
c
d
e f
a b
c d
Cycling through all elements in a list #
set lst [list a b c d e f]
puts $lst
puts "size of lst = [llength $lst]"
puts "first element of lst = [lindex $lst 0]"
puts "second element of lst = [lindex $lst 1]"
puts "second-to-last element of lst = [lindex $lst end-1]"
puts "last element of lst = [lindex $lst end]"
set list_idx 0
proc cycle_thru_lst {some_lst {inc 1}} {
global list_idx
set max_idx [llength $some_lst]
# puts "max index = $max_idx"
puts "some_list\[$list_idx\] = [lindex $some_lst $list_idx]"
if {$inc} {
if {$list_idx == $max_idx-1} {
set list_idx 0
} else {
incr list_idx
}
puts "increased list_idx = $list_idx"
} else {
if {$list_idx == 0} {
set list_idx [expr {$max_idx - 1}]
} else {
incr list_idx -1
}
puts "decreased list_idx = $list_idx"
}
}
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
cycle_thru_lst $lst 0
a b c d e f
size of lst = 6
first element of lst = a
second element of lst = b
second-to-last element of lst = e
last element of lst = f
some_list[0] = a
increased list_idx = 1
some_list[1] = b
increased list_idx = 2
some_list[2] = c
increased list_idx = 3
some_list[3] = d
increased list_idx = 4
some_list[4] = e
increased list_idx = 5
some_list[5] = f
increased list_idx = 0
some_list[0] = a
increased list_idx = 1
some_list[1] = b
increased list_idx = 2
some_list[2] = c
increased list_idx = 3
some_list[3] = d
decreased list_idx = 2
some_list[2] = c
decreased list_idx = 1
some_list[1] = b
decreased list_idx = 0
some_list[0] = a
decreased list_idx = 5
some_list[5] = f
decreased list_idx = 4
some_list[4] = e
decreased list_idx = 3
some_list[3] = d
decreased list_idx = 2
some_list[2] = c
decreased list_idx = 1
some_list[1] = b
decreased list_idx = 0
List available namespaces #
puts [namespace children ::]
::tcl
List all procs in a namespace #
puts "Procs in global (::) namespace:"
puts [info commands ::*]
puts ""
puts "Procs in ::tcl namespace:"
puts [info commands ::tcl::*]
Procs in global (::) namespace:
::tell ::socket ::subst ::open ::eof ::pwd ::glob ::list ::pid ::exec ::auto_load_index ::time ::unknown ::eval ::lassign ::lrange ::fblocked ::lsearch ::auto_import ::gets ::case ::lappend ::proc ::break ::variable ::llength ::auto_execok ::return ::linsert ::error ::catch ::clock ::info ::split ::array ::if ::fconfigure ::concat ::join ::lreplace ::source ::fcopy ::global ::switch ::auto_qualify ::update ::close ::cd ::for ::auto_load ::file ::append ::lreverse ::format ::unload ::read ::package ::set ::binary ::namespace ::scan ::apply ::trace ::seek ::while ::chan ::flush ::after ::vwait ::dict ::continue ::uplevel ::foreach ::lset ::rename ::fileevent ::regexp ::lrepeat ::upvar ::encoding ::expr ::unset ::load ::regsub ::history ::interp ::exit ::puts ::incr ::lindex ::lsort ::tclLog ::string
Procs in ::tcl namespace:
::tcl::pkgconfig ::tcl::CopyDirectory ::tcl::HistIndex ::tcl::HistEvent ::tcl::Bgerror ::tcl::HistInfo ::tcl::HistKeep ::tcl::HistAdd ::tcl::HistRedo ::tcl::dtrace ::tcl::HistChange ::tcl::HistClear