| Index
The Tcl language
- No fixed grammar
- Defined by the interpreter (parser) and
procedures that execute commands
- Case sensitive
Tcl Basics
Scripts, commands, and words
Tcl is a string-based, interpreted command
language. Its simplicity in syntax and common sensical approach to
semantics makes this an easy language to learn and become
proficient in. This short tutorial will concentrate on the most
basic concepts to get you started as quickly as possible.
A Tcl script consists of one or more commands,
separated by newlines or semicolons.
command arg1 arg2 arg3 ...
Commands are the basic execution elements. A
command is followed by zero or more words which are parameters or
arguments, each separated by white space or tabs.
ex: puts stdout "My first Tcl script."
= > My first Tcl script.
Evaluating a command
Two step process: parsing and execution.
- Parsing: Tcl does not apply any meaning to
the value of the words. It only performs simple string
operations, e.g. variable substitutions. Tcl only makes one
pass for substitutions (each character is scanned exactly
once). The result of one substitution is not scanned for
further substitutions.
- Execution: meaning is applied to the
arguments of the command. Tcl checks to see if the command is
defined, assumed to be the first word in the sequence of
words, and locates a command procedure to execute.
Note: arguments are quoted by default -- if you
want evaluation, you must ask for it explicitly
For example:
The first command assigns the string 5 to
variable a. The second command takes the string a+8 and stores
it as the new value for b. For y to take on the value 13, you
must explicitly evaluate it, as in:
Each pair of brackets invokes an additional
evaluation. The one thing you must remember about Tcl is that it
does just what you think it will. The evaluation model is very
straightforward. There is a single command and zero or more
arguments. Those arguments may in turn be commands with arguments
that must be evaluated. The commands' return values become the
argument to the original command to be evaluated.
Variable,command and backslash substitutions
State is maintained in Tcl through the use of
variables, and are both declared and instantiated with the
"set" command.
example:
set loopCounter 0
Note that a separate variable declaration is not
necessary. Variable values are retrieved using the dollar sign,
which will be familiar to shell programmers and Perl developers,
but there are slightly different rules associated with when and
when not to use the dollar sign.
example:
if
($loopCounter > 10) {
do something
}
- $ variable substitution: variables are
not declared -- they are all of type string of arbitrary
length. Variable substitution can occur anywhere in a word
(e.g. button .b$num).
- [ ] command substitution: everything
inside the brackets is evaluated as a Tcl script.
- \ backslash substitution: escape for
$, newline, quotes, etc.
Quoting and comments
- double quotes: spaces, tabs, newlines,
semicolons treated as ordinary characters (normal $, command,
and backslash substitution occur as usual).
- curly braces: all special characters
lose their meaning (no substitutions take place). Braces defer
evaluation.
- comments: if first non-blank character
is a '#', everything up to the newline is a comment. If '#'
occurs anywhere else, it is treated as an ordinary character.
Variables
Simple variables have a name and a value
(stored as a string).
Arrays are a collection of elements,
each of which is a variable with it own name and value. Array
names and element names may be arbitrary strings (i.e. sometimes
called associative arrays to distinguish them from arrays
that require elements to be integers).
Example:
set yearTotal 0
foreach month {Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} {
set yearTotal [expr $yearTotal+$earnings($month)]
}
Tcl only implements one-dimensional arrays, but multidimensional
arrays are simulated by concatenating multiple indices into a
single element name.
set matrix(1,1) 140
set matrix(1,2) 218
set matrix(1,3) 84
set i 1
set j 2
set cell $matrix($i,$j)
=> 218
*Note that there are no spaces because the
three element names are 1,1 and 1,2 and 1,3.
Thus:
matrix(2,5)
is not the same as
matrix(2, 5)
Expressions
Expressions combine operands and operators to
create new values.
Operators
- Relational operators (<, <=, >,
>=, ==, !=) return 0 (false) or 1 (true).
- Bitwise operators (&, |, ^, <<,
>>, ~) require operands to be integers.
<< and >> use the right
operand as the shift count (in bits). During left shifts,
zeros are shifted into the low order bytes. Right shifts are
"arithmetic right shifts" which shifts zeros for
positive number, and ones for negative numbers (unlike ANSI
C which is machine dependent). The ~ is a one's complement
operator that flips each bit.
- Choice operator is the ternary operator ?: if
first operand is true, evaluate the second operand, otherwise
evaluate the third operand.
Substitutions
Substitutions can occur in two ways for
expression operands.
- Through the normal Tcl parser mechanism
- Through expression evaluator which performs
an additional round of variable and command substitutions on
the expression while evaluating it.
Example:
expr { 2*sin($x) }
The braces causes Tcl parser to not do a
variable substitution for x. When the expression
evaluator encounters the dollar sign, it performs variable
substitution itself. This is not very useful for the exprcommand,
but is useful for other commands like while that evaluate
an expression repeatedly and expect to get a different result each
time.
Example:
set pow 1
while {$pow<$num} {
set pow [expr $pow*2]
}
If the braces were omitted in {$pow<$num},
the while's argument would be a constant expression such
as 1<44 which would cause in infinite loop.
String manipulation
Tcl allows string operands for some operators:
<, >, <=, >=, ==, and !=. For all other operators, the
operands must be numeric. Tcl only uses string comparisons if one
or both of the operands cannot be parsed as a number.
Example:
set x 0
set y 00
if {$x==$y} {
...
}
Arithmetic comparison will be used and the
test will evaluate to 1. To force string comparison for numeric
operands, use a command such as string compare.
Types and conversions
Tcl evaluates expressions numerically whenever
possible. String operations are performed only for the relational
operators and only if one or both of the operands doesn't make
sense as a number. Automatic conversion is done for operands of
different types:
- real and int: int => real
- non-numeric string and int/real: int/real
=> string
Also, use double, and int and round
to cast int to real and real to int respectively.
Precision
- integers (type int): 32 bits precision
- real (type double): 64 bits precision
- numbers are kept in internal form throughout
evaluation of an expression and are only converted back to
strings when necessary
- conversion of real to string defaults to 6
significant digits. Setting Tcl global variable tcl_precision
can change significant digits. Note: setting tcl_precision
to 17 on a machine that uses IEEE floating point will
guarantee that string conversions do not lose information
(e.g. when an expression is converted to string and then used
in a numeric calculation later).
Lists
A list is an ordered collection of elements
(separated by spaces) where each element can have any string
value. Lists can be nested.
| Command |
Result |
| concat ?list list ...? |
Joins multiple lists into a single list
(each element of each list becomes an element of
the result list) and returns the new list. |
| join list ?joinString? |
Concatenates list elements together with joinString
as separator and returns the result. joinString
defaults to a space. |
| lappend varName value
?value ...? |
Appends each value to variable varName
as a list element and returns the new value of the
variable. Creates the variable if it doesn't exist. |
| lindex list index |
Returns the index'th element from list
(0 refers to the first element). |
| linsert list index value ?value
...? |
Returns a new list formed by inserting
all of the value arguments as list elements before index'th
element of list (0 refers to the first element).
Example:
set x {a b {c d} e}
=> a b {c d} e
linsert $x 2 X Y Z
=> a b X Y Z {c d} e
|
| list ?value value ...? |
Returns a list whose elements are the value
arguments. |
| llength list |
Returns the number of elements in list. |
| lrange list first last |
Returns a list consisting of elements first
through last of list. If last is end,
it selects all elements up to the end of list. |
| lreplace list first last ?value
value ...? |
Returns a new list formed by replacing
elements first through last of list
with zero or more new elements, each formed from one value
argument. |
| lsearch ?-exact? ?-glob? ?-regexp? list
pattern |
Returns the index of the first element in
list that matches pattern or -1 if none. The
optional switch selects a pattern-matching technique
(default: -glob). |
| lsort ?-ascii? ?-integer? ?-real?
?-command command? ?-increasing? ?-decreasing? list |
Returns a new list formed by sorting the
elements of list. The switches determine the
comparison function and sorted order (default: -ascii
-increasing). |
| split string ?splitChars? |
Returns a list formed by splitting string
at instances of splitChars and turning the
characters between these instatnces into list elements. |
Control Flow
| if test1 body1 ?elseif test2
body2 elseif ...? ?else bodyn? |
|
| while test body |
|
| for init test reinit body |
|
| foreach varName list body |
|
switch ?options? string pattern
body ?pattern body ...?
switch ?options? string { pattern body ?pattern body
...? } |
Options: -exact (exact matching), -glob
(same as string matching), or -regexp (regular expression
matching).
If a script is '-', switch use the
script for next pattern (i.e. several patterns can all
execute the same script).
default pattern used to catch
unmatched patterns.
|
| eval arg ?arg arg ...? |
General purpose building block for
creating and executing Tcl scripts. It accepts any number
of arguments, concatenates all of the args with
separator spaces, then evaluates the result as a Tcl
script and returns its results which is useful when you
need to force another level of parsing. |
Procedures
Procedures are normal Tcl commands that are
useful in packaging modules that can be reused. Procedures can be
defined at any time and you can pass arguments by value or by
reference. The value returned is the result of the last statement
in the body of the procedure, unless explicitly returned with the return
command.
Syntax:
e.g.:
proc plus {a b} {expr $a+$b}
Arguments
Arguments used inside a procedure are local. To
reference global variables, the global command will bind
variables within the procedure for the life of the procedure.
Arguments can have default values and are specified as follows:
proc inc {value {increment 1}} {
expr $value+$increment
}
incr 42 3
=> 45
incr 42
=> 43
Defaulted arguments, if any, must be the last
arguments for the procedure. If a default is not specified, the
argument is required.
Variable number of arguments is supported by args
which is put at the end of the argument list. The procedure uses
the args argument as a list whose elements are the extra
arguments. If there are no extra arguments, args will be
set to an empty string.
proc sum args {
set s 0
foreach i $args {
incr s $i
}
return $s
}
sum 1 2 3 4 5
=> 15
sum
=> 0
Call by reference
The upvar command provides a general
mechanism for accessing variables outside the context of a
procedure. It can be used to access global or local variables in
some other active procedure, but is most often used to pass in
arrays (because there is no value for an array, just its
elements).
Example:
proc parray name {
upvar $name a
foreach el [lsort [array names a]] {
puts "$el = $a($el)"
}
}
set info(age) 37
set info(position) "Vice President"
parray info
=> age = 37
position = Vice President
upvar can also be used to access
variables on different levels of the call stack.
makes global variable other accessible
via local variable x (#0 specifies access to the
global variable other regardless of the level of the call
stack).
makes variable other in the caller of
the caller of the current procedure accessible as local
variable x (2 specifies two levels up in the call stack).
Creating new control structures
uplevel is a command that is a cross
between eval and upvar. It evaluates its
argument(s) as a script, just like eval, but the script
is evaluated in the variable context of a different stack level
like upvar. With uplevel, you can define new
control structures as Tcl procedures.
Example:
proc do {varName first last body}{
upvar $varName v
for {set v $first} {$v <= $last} {incr v}
uplevel $body
}
}
set squares {}
do i 1 5 {
lappend squares [expr $i*$i]
}
set squares
=> 1 4 9 16 25
Like upvar, uplevel takes an
optional inital argument that specifies an explicit stack level.
String Manipulation
Tcl is 8 bit clean (not just ASCII 7 bit
subset). Tcl does not apply any interpretation to characters
outside of the ASCII subset. Tcl stores strings using a null
(zero) character for termination, so it is not possible to store
zero characters in a string. To represent binary data, convert it
to a form that includes no zero characters, for example, by
translating bytes to their corresponding hexadecimal values.
Glob-style pattern matching
Simplest form of Tcl pattern matching.
Syntax:
Return 1 if match, 0 if no match. Special
characters used in matching
| * |
Matches any sequence of zero or more
characters. |
| ? |
Matches any single character. |
| [chars] |
Matches any single character in chars.
If chars contains a sequence of the form a-b,
any character between a and b inclusive will match. |
| \x |
Matches the single character x.
This provides a way to avoid special interpretation for
any of the characters *?[]\ in the pattern. |
Pattern matching with regular expressions
Regular expression patterns can have several
layers of structure. Basic building blocks are called atoms
and the simplest form regular expression consists of one or more
atoms. For a regular expression to match an input string, there
must be a substring of the input where each of the regular
expression's atoms (or other components) matches the corresponding
part of the substring. E.g. regular expression abc
matches any string containing abc such as abcdef
or xabcy.
For example, the following pattern matches any
string that is either a hexadecimal number or a decimal number.
Syntax:
and returns 0 if there is no match, 1 if there
is a match.
Note, the pattern must be enclosed in braces
so that the characters $, [, and ] are
passed through to the regexp command instead of
triggering variable or command substitution.
If regexp is invoked with arguments after the
input string, each argument is treated as a name of a variable.
The first variable is filled in with the substring that matched
the entire regular expression. The second variable is filled in
with the portion of the substring that matched the leftmost
leftmost parenthesized subexpression within the pattern; the third
third variable is filled in with the the match for the next
parenthesized subexpression and so on. If there are more variables
names than parenthesized subexpressions, the extra variables are
set to empty strings.
Example:
variable a will have the value "10
km", b will have "10" and c
will have "km".
The switch -nocase specifies to match
without case sensitivity. The switch -indices specifies
that the additional variables should not be filled in with the
values of the matching substrings, but with a list giving the
first and last indices of the substring's range within the input
string.
Example:
variable a will have the value "5
9", b will have "5 6" and c
will have "8 9".
| Characters |
Meaning |
| . |
Matches any single character |
| ^ |
Matches the null string at the start of
the input string. |
| $ |
Matches the null string at the end of the
input string. |
| \x |
Matches the character x. |
| [chars] |
Matches any single character from chars.
If the first character of chars is ^, the pattern
matches any single character not in the remainder of chars.
A sequence in the form of a-b in chars is
treated as shorthand for all of the ASCII characters
between a and b inclusive. If the first
character in chars (possibly following a ^) is ],
it is treated literally (as part of chars instead
of a terminator). If a - appears first or last in chars,
it is treated literally. |
| (regexp) |
Matches anything that matches the regular
expression regexp. Used for grouping and for
identifying pieces of the matching substring. |
| * |
Matches a sequence of 0 or more matches
of the preceding atom. |
| + |
Matches a sequence of 1 or more matches
of the preceding atom. |
| ? |
Matches either a null string or a match
of the preceding atom. |
| regexp1 | regexp2 |
Matches anything that matches either regexp1
or regexp2. |
Using regular expressions for substitutions
Syntax:
The first argument to regsub is the
regular expression pattern. If a match is found in the input
string, regsub return 1, otherwise it returns 0 (like regexp
command). If the pattern is matched, the substring of the input
string is replaced by the third argument and the new string is
stored in the fourth argument. If a match was not found, the
fourth argument contains the original input string. Two switches
can be used: -nocase is equivalent to the nocase switch
in the regexp command; -all causes every matching
substring in the input string to be replaced.
Formatted output
The format command provides facilities
like sprintf in ANSI C.
Example:
Other format specifiers:
| %s |
String |
| %d |
Decimal integer |
| %f |
Real number |
| %e |
Real number in mantissa-exponent form |
| %x |
Hexadecimal |
| %c |
Character |
The format command can also be used to change
the representation of a value. For example, formatting an integer
with %c generates the ASCII character represented by the integer.
Parsing strings with scan
Syntax:
scan parse_string format_string
?variable ...?
Example:
scan "16 units, 24.2 margin"
"%d units, %f" a b
=> 2
Character functions
String manipulation commands are options of the string
command.
string index "See Spot run." 5
=> p
string range "See Spot run." 5 8
=> Spot
string range "See Spot run." 5
end
=> Spot run.
Seaching and comparison
Searching for a substring with first or
last returns the position of the first character of the
substring (starting at 0 for the first character in the input
string). Returns -1 if no match was found.
string first th "The trains were thirty
minutes late this past week"
=> 16
string last th "The trains were thirty
minutes late this past week"
=> 36
Compare returns 0 if the strings match, -1 if
the first string sorts before the second, and 1 if the first
string sorts after the second.
string compare twelve thirteen
=> 1
string compare twelve twelve
=> 0
Length, case conversion, and trimming
string length "not too long"
=> 12
string toupper "Hello, World!"
=> HELLO, WORLD!
string tolower "You are lucky winner
13!"
=> you are lucky winner 13!
string trim abracadabra abr
=> cad
string trim takes a string to trim and
an optional set of trim characters and removes all instances of
the trim characters from both the beginning and end of its
argument string, returning the trimmed string as result. trimleft
and trimright options work in the same way except they
only remove the trim characters from the beginning or end of the
string. The trim comands are mostly commonly used to remove excess
white space; if no trim characters are specified, they default to
the white space characters (space, tab, newline, carriage return,
and form feed).
Resources
Many of the examples above are from John
Ousterhout's book:
Tcl and the Tk Toolkit
Author: John K. Ousterhout
Publisher: Addison Wesley, 1994
While there are many more books on the Tcl
language, this book, in my opinion, is one of the best.
工具命令语言简介
|