Red Hat Linux 9 Professional Secrets [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Red Hat Linux 9 Professional Secrets [Electronic resources] - نسخه متنی

Naba Barkakati

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








Introducing Tcl


The creator of Tcl, John Ousterhout, intended it to be a simple, embeddable scripting language whose interpreter could be linked with any C program, so that the C program could use Tcl scripts. The term embeddable refers to this property of Tcl-the capability of any C program to use the Tcl interpreter and run Tcl scripts.

John Ousterhout created Tcl and Tk when he was at the University of California at Berkeley. Tcl first appeared in 1989; Tk followed in 1991. Tcl/Tk are freely available for unrestricted use, including commercial use. At the time of this writing, the current Tcl version is 8.3; Tk is also 8.3. Red Hat Linux comes with Tcl/Tk.

The following sections provide an overview of Tcl, its syntax, and some of its important commands. Because Tcl underlies the Tk toolkit, you should become familiar with Tcl before jumping into Tk, although Tk undoubtedly is more fun because you can use it to create graphical interfaces.


Writing Your First Tcl Script


In Chapter 24, you learned how to write shell scripts and Perl scripts. You write Tcl scripts the same way. Unlike Perl, Tcl includes a shell-an interactive interpreter of Tcl commands. The Tcl shell program's name is tclsh; it should be in the

/usr/bin directory.

When you log in, the

PATH environment variable should include the

/usr/bin directory. Thus, you can start the Tcl shell by typing

tclsh at a text console or in a terminal window in GNOME or KDE. A percent sign (

% ) appears on the next line; this is the Tcl shell program's prompt. To see which version of Tcl you have, type info tclversion at the Tcl shell prompt. The Tcl shell program responds by printing the version of Tcl. Here is an example of how you interact with the Tcl shell:


tclsh
% info tclversion
8.3
%

Now you can interactively try the following Tcl program, which prints

Hello, World! on the standard output (the display screen or the terminal window):

% puts "Hello, World!"
Hello, World!
% exit

Type exit to quit the Tcl shell.





Note

Note that I don't show the shell prompt in previous chapters, but I show the Tcl prompt (%) in many of this chapter's code listings. That's because the Tcl prompt looks different from the Bash prompt, which should tell you that you aren't working in Bash.


The Tcl shell immediately processes the Tcl command you enter and displays the results, then it prompts you for the next input. At this point, you can type exit to quit the Tcl shell (

tclsh ).

To prepare and run a Tcl script, follow these steps:



  1. Use a text editor to enter and save the following lines in a file named

    hellotcl (this file will be the Tcl script):

    #!/usr/bin/tclsh
    # A simple Tcl script
    puts "Hello, World!"



  2. Type the following command at the shell prompt to make the

    hellotcl file executable (that's what the

    +x in the

    chmod command means):

    chmod +x hellotcl



  3. To run the

    hellotcl script, type the following at the shell prompt:


    ./hellotcl
    Hello, World!



Use these basic steps to create and run any Tcl script. You still have to learn the nuances of Tcl syntax, of course-as well as many rules. This section gets you started with an overview of Tcl.


Getting More Information on Tcl/Tk


This chapter provides an overview of Tcl and Tk, highlights many key points, and shows simple examples. However, there isn't enough room in this chapter to list all the information you need to fully exploit the power of Tcl and Tk. Because of Tcl/Tk's popularity, you can find quite a few resources about it, ranging from books to Internet sites. Following is a short list of Tcl/Tk resources:



  • Books -Two prominent books on Tcl/Tk are available. The first book is Tcl and the Tk Toolkit (Addison Wesley 1994) by John K. Ousterhout, the originator of Tcl and Tk. John's book provides a broad overview of Tcl and Tk, including an explanation of the way that Tcl command strings are parsed. The other book is Practical Programming in Tcl and Tk, Third Edition (Prentice Hall 2000) by Brent B. Welch. This book provides more Tcl and Tk examples.



  • Internet resources-Several FTP and websites contain the latest Tcl/Tk distributions and information about Tcl/Tk development. Following are the URLs for a few key sites:





Getting an Overview of Tcl


True to its name (Tool Command Language), Tcl consists of a set of commands you can combine according to a set of rules. To write Tcl scripts, you have to understand two broad subjects:



  • Tcl syntax-Tcl syntax is the set of rules the Tcl command interpreter follows when it interprets a command string (a line that contains a command and its arguments).



  • Tcl commands-Although the syntax is the same for all commands, each Tcl command is meant to perform a specific task. To exploit Tcl fully, you have to know what commands are available and what each command does. The Tcl command set can be extended by applications. In fact, Tk itself is an extension of Tcl; Tk adds commands that manipulate components of GUIs.



Start by learning the Tcl syntax, a handful of rules that determine the way each Tcl command is parsed. Because Tcl has many commands, learning all of them can take a while. Even after you become proficient in the Tcl syntax and a small set of commands, you may need to keep a reference manual nearby so that you can check the exact format of the arguments that each command requires.

Tcl commands include the following basic programming facilities that you expect from any programming language:



  • Variables, which store data. Each variable has a name and a value. Tcl also allows you to define arrays of variables.



  • Expressions, which combine values of variables with operators. An expression might add two variables, for example. Tcl uses the

    expr command to evaluate expressions.



  • Control-flow commands, which enable commands to be executed in various orders, depending on the value of some expression. Tcl provides commands such as

    for ,

    foreach ,

    break ,

    continue ,

    if ,

    while , and

    return to implement flow control in Tcl scripts.



  • Procedures, which enable you to group several commands and give them a name. Procedures also accept arguments. Tcl provides the

    proc command to enable you to define procedures. You can use a procedure to execute the same set of commands (usually with different arguments) by invoking the procedure that represents those commands.



The next few sections provide an overview of the Tcl syntax and the core Tcl commands.


Learning the Basic Tcl Syntax


To understand the basic Tcl syntax, you have to know a bit about how the Tcl interpreter processes each command string. The steps are as follows:



  1. The Tcl interpreter parses (breaks down) the command string into words-the constituent parts, including variables and operators.



  2. The Tcl interpreter applies rules to substitute the values of variables and replace certain commands with their results.



  3. The Tcl interpreter executes the commands, taking the first word as the command name and calling a command procedure to execute the command. The command procedure receives the rest of the words as strings.



When writing Tcl command strings, you have to use white space (a space or a tab) to separate a command's name from its arguments. A newline or a semicolon (

; ) marks the end of a command string. You can put two commands on the same line if you insert a semicolon after the first command. Thus, you can use the following:

% puts Hello, ; puts World!
Hello,
World!

The resulting output appears on separate lines because the puts command adds a newline by default.

Use a backslash (

\ ) at the end of a line to continue that command string on the next line (this is a standard convention in UNIX). Thus, you can write a command string to print Hello, World! as follows:

puts "Hello, World!"


Substitutions


The Tcl interpreter replaces certain parts of the command string with an equivalent value. If you precede a variable's name with a dollar sign (

$ ), for example, the interpreter replaces that word with the variable's value. As you learn in the 'Variables' section, you can define a variable in a Tcl script by using the

set command, as follows:

set count 100

This command defines a variable named

count with the value 100. Suppose that you type the following:

puts $count

The interpreter first replaces

$count with its value, 100. Thus, that command string becomes:

puts 100

When the interpreter executes the

puts command, it prints 100. This is an example of variable substitution.

In all, the Tcl interpreter supports three kinds of substitutions:



  • Variable substitution-As the preceding example shows, if the Tcl interpreter finds a dollar sign (

    $ ), it replaces the dollar sign as well as the following variable name with that variable's value.



  • Backslash substitution-You can embed special characters, such as the newline and tab, in a word by using backslash substitution. Type a backslash, followed by one or more characters; the interpreter replaces that sequence with a nonprintable character. These sequences are patterned after ANSI Standard C's escape sequences. Table 25-1, which follows this list, summarizes the backslash sequences that the Tcl interpreter understands.



  • Command substitution-This type of substitution refers to the mechanism that enables you to specify that a command be evaluated and replaced by its result before the interpreter processes the command string. The command

    string length "Hello, World!" , for example, returns 13, the length of the string. To set a variable named

    len to the length of this string, type the following:

    set len [string length "Hello, World!"]

    The interpreter processes the command inside the square brackets and replaces that part of the command string with the value of the command. Thus, this command becomes

    set len 13

    and the

    set command sets the

    len variable to 13.
















































    Table 25-1: Backslash Sequences and Their Meanings in Tcl


    Sequence


    Replacement Character *


    \a


    Bell character (0x7)


    \b


    Backspace (0x8)


    \f


    Form feed (0xc)


    \n


    Newline (0xa)


    \r


    Carriage return (0xd)


    \t


    Horizontal tab (0x9)


    \v


    Vertical tab (0xb)


    \ <

    newline >


    Replace the newline and white space on the next line with a single space


    \\


    Interpret as a single backslash (

    \ )


    \"


    Interpret as double quotation marks (

    " )


    \

    ooo


    Use the value specified by the octal digits

    ooo (up to three)


    \x

    hh


    Use the value specified by the hexadecimal digits

    hh (up to two)




* Hexadecimal values are shown in parentheses (for example, 0xd means hexadecimal d)


Comments


A pound sign (#) marks the start of a comment; the Tcl interpreter disregards the rest of the line, beginning with the pound sign. Tcl does, however, have a peculiar requirement for comments: you cannot start a comment within a command. The command string must end before you start a comment.

To understand this problem, try the following Tcl command at the

tclsh prompt:

% puts "Hello, World!" # This is a comment
wrong # args: should be "puts ?-nonewline? ?channelId? string"
%

Essentially, the

puts command processes the remainder of the line and complains about the number of arguments. The solution is to put a semicolon just before the pound sign (

# ), as follows:

% puts "Hello, World!" ;# This is a comment
Hello, World!






Insider Insight

If you put comments at the end of a Tcl command, remember to precede the pound sign (

# ) with a semicolon (

; ). The semicolon terminates the preceding command and enables you to start a comment.



Braces and Double Quotation Marks


You can use braces (

{...} ) and double quotation marks (

"..." ) to group several words. Use double quotes to pass arguments that contain an embedded space or a semicolon, which otherwise ends the command. The quotes are not part of the group of words; they simply serve to mark the beginning and end of a group of words. Following are some examples of using double quotes to group words:

% puts "Hello, World!"
Hello, World!
% puts "Enter 1; otherwise file won't be saved!"
Enter 1; otherwise file won't be saved!

When you group words with double quotes, all types of substitutions still take place, as the following example illustrates:

% puts "There are [string length hello] characters in 'hello'"
There are 5 characters in 'hello'

The Tcl interpreter replaces everything inside the brackets with the result of the

string length hello command, whose return value is the number of characters in

hello (

5 ). In the expression

[string length hello] , you can replace the string

hello with any variable to determine the length of that variable's value.

Also, you can use braces to group words. The Tcl interpreter does not perform any substitutions when you group words with braces (if you enclose words in double quotes, the interpreter does perform a substitution). Consider the preceding example with braces instead of double quotes:

% puts {There are [string length hello] characters in 'hello'}
There are [string length hello] characters in 'hello'

As the result shows, the Tcl interpreter simply passes everything, unchanged, as a single argument.






Insider Insight

Use braces as a grouping mechanism when you have to pass expressions to control commands, such as while loops, for loops, or procedures.



Understanding Tcl Variables


Everything is a string in Tcl. Variable names, as well as values, are stored as strings. To define a variable, use the built-in Tcl command

set . The following commands, for example, define the variable

book as

"Red Hat Linux Professional Secrets"; the variable

year as

2003; and the variable

price as

$49.99 :

set book "Red Hat Linux Professional Secrets"
set year 2003
set price \$49.99

To refer to the value of a variable, add a dollar sign (

$ ) prefix to the variable's name. Therefore, to print the variable

book , use the following format:

% puts $book
Red Hat Linux Professional Secrets

If you use set with a single argument, set returns the value of that argument. Thus, set book is equivalent to

$book , as the following example shows:

% puts [set book]
Red Hat Linux Professional Secrets


Writing Expressions


You can write expressions by combining variables with mathematical operators, such as

+ (add),

- (subtract),

* (multiply), and

/ (divide). Here are some examples of expressions:

set count 1
$count+1
$count + 5 - 2
2 + 3.5

You can use numbers, as well as variable names, in expressions. Use white space to enhance readability. Use parentheses to specify how you want an expression to be evaluated.

In addition to the basic mathematical operators, Tcl includes several built-in mathematical functions, such as

sin ,

cos ,

tan ,

log , and

sqrt . Call these functions just as you do in C, with arguments in parentheses, as follows:

set angle 1.5
2*sin($angle)

In addition, you can use Boolean operators, such as

! (not), && (and), and

|| (or). Comparison operators-such as < (less than), > (greater than), <

= (less than or equal to),

== (equal to), and

!= (not equal to)-also are available. Expressions that use Boolean or comparison operators evaluate to 1 if true and 0 if false. You can write expressions, such as the following:

count == 10
angle < 3.1415

Expressions are not commands by themselves. You can use expressions as arguments only for commands that accept expressions as arguments. The

if and

while commands, for example, expect expressions as arguments.

Tcl also provides the

expr command to evaluate an expression. The following example shows how you might evaluate an expression in a Tcl command:

% set angle 1.5
1.5
% puts "Result = [expr 2*sin($angle)]"
Result = 1.99498997321

Although Tcl stores everything as a string, you have to use numbers where numbers are expected. If

book is defined as

"Red Hat Linux Professional Secrets" , for example, you cannot write an expression

$book+1 , because it does not make sense.


Using Control-Flow Commands in Tcl


Tcl's control-flow commands enable you to specify the order in which the Tcl interpreter executes commands. You can use the

if command to test the value of an expression; and if the value is true (nonzero), you can make the interpreter execute a set of commands. Tcl includes control-flow commands similar to those in C, such as

if ,

for ,

while , and

switch . This section provides an overview of the control-flow commands.








Secret


A Tcl control-flow command typically has a command block (a group of commands) that the control-flow command executes after evaluating an expression. To avoid substitutions (such as replacing variables with their values), you must enclose the entire command block in braces. The following

if -

else control-flow commands illustrate the style of braces that works properly:

 if { expression } {
# Commands to execute when expression is true
command_1
command_2
} else {
# Commands to execute when expression is false
# ...
}

You should follow this style of braces religiously in Tcl scripts. In particular, remember to include a space between the control-flow command (such as

if ) and the left brace (

{ ) that follows the command.












Using the if Command


In its simplest form, Tcl's

if command evaluates an expression and executes a set of commands if that expression is nonzero (true). You might compare the value of a variable with a threshold as follows:

if { $errorCount > 25 } {
puts "Too many errors!"
}

You can add an

else clause to process commands if the expression evaluates to zero (false). Following is an example:

if { $user == "root" } {
puts "Starting system setup ..."
} else {
puts "Sorry, you must be \"root\" to run this program!"
}

Tcl's

if command can be followed by zero or more

elseif commands if you need to perform more complicated tests, such as the following:

puts -nonewline "Enter version number: "  ;# Prompt user
set version [gets stdin] ;# Read version number
if { $version >= 10 } {
puts "No upgrade necessary"
} elseif { $version >= 6 && $version < 9} {
puts "Standard upgrade"
} elseif { $version >= 3 && $version < 6} {
puts "Reinstall"
} else {
puts "Sorry, cannot upgrade"
}


Using the while Command


The

while command executes a block of commands until an expression becomes false. The following

while loop keeps reading lines from the standard input until the user presses Ctrl+D:

while { [gets stdin line]  != -1 } {
puts $line
# Do whatever you need to do with $line.
}

Although this

while command looks simple, you should realize that it has two arguments inside two sets of braces. The first argument is the expression; the second argument contains the Tcl commands to be executed if the expression is true. You must always use braces to enclose both of these arguments. The braces prevent the Tcl interpreter from evaluating the contents; the

while command is the one that processes what's inside the braces.

If you use a variable to keep count inside a while loop, you can use the

incr command to increment that variable. You can skip to the end of a loop by using the

continue command; the

break command exits the loop. The following Tcl script uses a while loop to add all the numbers from 1 to 10, except 5:

#!/usr/bin/tclsh
set i 0
set sum 0
while { 1 } {
incr i ;# Increment i
if {$i == 5} { continue } ;# Skip if i is 5
if {$i > 10} {break } ;# End loop if i exceeds 10
set sum [expr $sum+$i] ;# Otherwise, add i to sum
}
puts "Sum = $sum";

When you run this script, it should display the following result:

Sum = 50


Using the for Command


Tcl's

for command takes four arguments, which you should type in the following manner:

for {expr1} { expr2} { expr3} {
commands
}

The

for command evaluates

expr1 once at the beginning of the loop and executes the commands inside the final pair of braces, until the expression

expr2 evaluates to zero. The

for command evaluates the third expression-

expr3 -after each execution of the commands. You can omit any of the expressions, but you must use all the braces. The following example uses a

for loop to add the numbers from 1 to 10:

#!/usr/bin/tclsh
for {set i 0; set sum 0} {$i <= 10} {set sum [expr $sum+$i]; incr i} {
}
puts "Sum = $sum";

When you run this script, it displays the following result:

Sum = 55


Using the foreach Command


You have not seen a command like

foreach in C, but

foreach is handy when you want to perform some action for each value in a list of variables. You can add a set of numbers with the

foreach command as follows:

set sum 0
foreach i { 1 2 3 4 5 6 7 8 9 10} {
set sum [expr $sum+$i]
}
puts "Sum = $sum"

When you run this script, this one also prints

Sum = 55 because the script is adding the numbers 1 through 10.

If you have a list in a variable, you can use that variable's value in place of the list shown within the first pair of braces. Following is a

foreach loop that echoes the strings in a list:

set users "root naba"
foreach user $users {
puts "$user"
}


Using the switch Command


Tcl's

switch command is different from C's

switch statement. Instead of evaluating a mathematical expression, Tcl's

switch command compares a string with a set of patterns and executes a set of commands, depending on which pattern matches. Often, the pattern is expressed in terms of a regular expression.






Cross Ref

See Chapter 24 for an introduction to regular expressions.


The following script illustrates the syntax and a typical use of the

switch command:

#!/usr/bin/tclsh
# This script reads commands from the user and processes
# the commands using a switch statement.
set prompt "Enter command (\"quit\" to exit): "
puts -nonewline "$prompt"; flush stdout
while { [gets stdin cmd] != -1 } {
switch -exact -- $cmd {
quit { puts "Bye!"; exit}
start { puts "Started"}
stop { puts "Stopped"}
draw { puts "Draw.."}
default { puts "Unknown command: $cmd" }
}
# Prompt user again
puts -nonewline $prompt; flush stdout
}

Following is a sample session with this script (user input is in boldface):

Enter command ("quit" to exit): help
Unknown command: help
Enter command ("quit" to exit): start
Started
Enter command ("quit" to exit): stop
Stopped
Enter command ("quit" to exit): quit
Bye!

As this example shows, the

switch statement enables you to compare a string with a set of other strings and to activate a set of commands, depending on which pattern matches. In this example, the string is

$cmd (which is initialized by reading the user's input with a

gets command), and the patterns are literal strings:

quit ,

start ,

stop , and

draw .








Secret


When you want the

switch statement to compare a string with a set of other strings and look for an exact match, use the

-exact flag on the first line of the

switch command, as follows:

switch -exact -- $cmd {
...
}

The two hyphens (

- ) immediately after the

-exact flag mark the end of the flags. When you use the

switch command, you should always use the double hyphens at the end of the flag to prevent the test string (in this example, the test string is

$cmd ) from matching a flag inadvertently.

You can use the

switch command with the

-regexp flag to compare a string with a regular expression, as in the following example:

# Assume that $cmd is the string to be matched.
switch -regexp -- $cmd {
^q.* { puts "Bye!"; exit}
^x.* { puts "Something x..."}
^y.* { puts "Something y..."}
^z.* { puts "Something z..."}
default { puts "Unknown command: $cmd" }
}

In this example, each regular expression has a similar form. The pattern

^z.* means any string that starts with a single

z , followed by any number of other characters.












Writing Tcl Procedures


You can use the

proc command to add your own commands. Such commands are called procedures; the Tcl interpreter treats them just as though they were built-in Tcl commands. The following example shows how easy it is to write a procedure in Tcl:

#!/usr/bin/tclsh
proc total items {
set sum 0
foreach i $items {
set sum [expr $sum+$i]
}
return $sum
}
set counts "5 4 3 5"
puts "Total = [total $counts]"

When you run the preceding script, it prints the following:

Total = 17

In this example, the procedure's name is

total , and it takes a list of numbers as the argument. The procedure receives the arguments in the variable named

items . The body of the procedure extracts each item and returns a sum of the items. Thus, to add numbers from 1 to 10, you have to call the

total procedure as follows:

set sum1_10 [total {1 2 3 4 5 6 7 8 9 10}]








Secret


In a Tcl procedure, the argument name

args has special significance; if you use

args as the argument name, you can pass a variable number of arguments to the procedure. For example, write the

total procedure with the argument name as

args , as follows:

proc total args {
set sum 0
foreach i $args {
set sum [expr $sum+$i]
}
return $sum
}

Now, you can call total in the following manner:

set sum1_10 [total 1 2 3 4 5 6 7 8 9 10]   ;# Variable arguments

This should set

sum1_10 to the sum of the numbers from 1 through 10.











If you want to access a global variable (a variable defined outside a procedure) in the Tcl procedure, you have to use the

global command inside the procedure. The

global command makes a global variable visible within the scope of a procedure. If a variable named

theCanvas holds the current drawing area in a Tk (Tcl's X toolkit) program, a procedure that uses

theCanvas must include the following command:

global theCanvas


Taking Stock of Built-in Tcl Commands


You have seen many Tcl commands in the preceding examples. Knowing the types of commands that are available in Tcl helps you decide which commands are most appropriate for the task at hand. Although this chapter does not have enough room to cover all Tcl commands, Table 25-2 summarizes Tcl's built-in commands.






Insider Insight

To get online help about any Tcl command listed in Table 25-2, type

man n , followed by the command name. To get online help about Tcl's file command, for example, type

man n file .




































































































































































































Table 25-2: Built-in Tcl Commands


Command


Action


append


Appends an argument to a variable's value


array


Performs various operations on an array variable


break


Exits a loop command (such as while and for)


catch


Executes a script and traps errors to prevent errors from reaching the Tcl interpreter


cd


Changes the current working directory


close


Closes an open file


concat


Joins two or more lists in a single list


continue


Immediately begins the next iteration of a for or while loop


eof


Checks to see whether end-of-file is reached in an open file


error


Generates an error


eval


Concatenates lists (as

concat does), and then evaluates the resulting list as a Tcl script


exec


Starts one or more processes that execute the command's arguments


exit


Terminates the Tcl script


expr


Evaluates an expression


file


Checks filenames and attributes


flush


Flushes buffered output to a file


for


Implements a for loop


foreach


Performs a specified action for each element in a list


format


Formats output and stores it in a string (as the

sprintf function in C does)


gets


Reads a line from a file


glob


Returns the names of files that match a pattern (such as

*.tcl )


global


Accesses global variables


history


Provides access to the history list (the list of past Tcl commands)


if


Tests an expression and executes commands if the expression is true (nonzero)


incr


Increments the value of a variable


info


Returns internal information about the Tcl interpreter


join


Creates a string, by joining all items in a list


lappend


Appends elements to a list


lindex


Returns an element from a list at a specified index. (Index 0 refers to the first element.)


linsert


Inserts elements into a list before a specified index


list


Creates a list composed of the specified arguments


llength


Returns the number of elements in a list


lrange


Returns a specified range of adjacent elements from a list


lreplace


Replaces elements in a list with new elements


lsearch


Searches a list for a particular element


lsort


Sorts a list in a specified order


open


Opens a file and returns a file identifier


pid


Returns the process identifier (ID)


proc


Defines a Tcl procedure


puts


Sends characters to a file


pwd


Returns the current working directory


read


Reads a specified number of bytes from a file. (You can read the entire file in a single read.)


regexp


Matches a regular expression with a string


regsub


Substitutes one regular expression pattern for another


rename


Renames or deletes a command


return


Returns a value from a Tcl procedure


scan


Parses a string, using format specifiers patterned after C's

sscanf function


seek


Changes the access position (where the next input or output operation occurs) in an open file


set


Sets a variable's value or returns its current value


source


Reads a file and processes it as a Tcl script


split


Breaks a string into a Tcl list


string


Performs various operations on strings


switch


Processes one of several blocks of commands, depending on which pattern matches a specified string


tell


Returns the current access position for an open file


time


Returns the total time needed to execute a script


trace


Executes a specified set of Tcl commands whenever a variable is accessed


unknown


Handles any unknown command. (The Tcl interpreter calls this command whenever it encounters any unknown command.)


unset


Removes the definition of one or more variables


uplevel


Executes a script in a different context


upvar


References a variable outside a procedure. (This is used to implement the pass-by-reference style of procedure call, in which changing a procedure argument changes the original copy of the argument.)


while


Implements a while loop that executes a set of Tcl commands repeatedly, as long as an expression evaluates to a nonzero value (true)



Manipulating Strings in Tcl


If you browse through the Tcl commands listed in split ,

string ,

regexp , and

regsub -that operate on strings. This section summarizes a few string-manipulation commands.








Secret


When you set a variable to a string, the Tcl interpreter considers that string to be a single entity, even if that string contains embedded spaces or special characters. Sometimes you need to access the string as a list of items. The

split command is a handy way to separate a string into its components. The lines in the

/etc/passwd file, for example, look like the following:

root:x:0:0:root:/root:/bin/bash

The line is composed of fields separated by colons (

: ). Suppose that you want to extract the first field from each line (because that field contains the login name). You can read the file one line at a time, split each line into a list, and extract the first element (the item at index 0) of each list. Following is a Tcl script that does this:

#!/usr/bin/tclsh
set fid [open "/etc/passwd" r] ;# Open file for read-only access
while { [gets $fid line] != -1 } {
set fields [split $line ":"] ;# Split the string into a list
# Just print out the first field
puts [lindex $fields 0] ;# Extract item at a index 0
}

When you run this script, it prints all the login names from your system's

/etc/ passwd file.











The

join command is the opposite of

split; you can use it to create a single string from the items in a list. Suppose that you have a list of six items, defined as follows:

set x {1 2 3 4 5 6}

When you join the elements, you can select what character you want to use between fields. To join the elements without anything in between them, use the following format:

set y [join $x "]

Now the y string is

"123456" .

The

string command is a group of commands for working with strings; the first argument of

string specifies the operation to be performed. The

string compare command, for example, compares two strings, returning zero when the two strings are identical. A return value of

-1 indicates that the first string argument is lexicographically less than the second one, which means it appears before the second one in a dictionary. Similarly, a

1 return value indicates that the first string is lexicographically greater than the second one. Thus, you might use

string compare in an

if command as follows:

if { [string compare $command "quit"] == 0} {
puts "Exiting..."
exit 0
}

Table 25-3 lists the operations you can perform with Tcl's

string command.
















































Table 25-3: Operations You Can Perform with String in Tcl


String Command


Description


string compare

string1 string2


Returns

-1 ,

0 , or

1 after comparing strings


string first

string1 string2


Returns the index of the first occurrence of

string1 in

string2


string index

string charIndex


Returns the character at index

charIndex


string last

string1 string2


Returns the index of the last occurrence of

string1 in

string2


string length

string


Returns the length of the

string


string match

pattern string


Returns

1 if the

pattern matches the

string , and

0 if it does not


string range

string first last


Returns a range of characters from

string


string tolower

string


Returns the

string in lowercase characters


string toupper

string


Returns the

string in uppercase characters


string trim

string chars


Returns the

string after trimming the leading or trailing characters


string trimleft

string chars


Returns the

string after trimming the leading characters


string trimright

string chars


Returns the

string after trimming the trailing characters




Using Arrays


In Tcl, an array is a variable with a string index. An array contains elements; the string index of each element is called the element name. In other words, you can access an element of an array by using its name. Internally, Tcl implements arrays with an efficient data structure known as a hash table, which enables the Tcl interpreter to look up any array element in a relatively constant period of time.

Declare an array variable by using the

set command. The following example shows how you might define the

disk_usage array that holds the amount of disk space a system's users consume:

set disk_usage(root)         147178
set disk_usage(naba) 28574
set disk_usage(emily) 73
set disk_usage(ivy) 61
set disk_usage(ashley) 34

After you define the array, you can access its individual elements by element name, as in the following example:

set user "naba"
puts "Disk space used by $user = $disk_usage($user)K"


Accessing Environment Variables in Tcl


Tcl provides the environment variables in a predefined global array named

env , with the environment-variable names used as element names. In other words, you can look up the value of an environment variable by using the variable name as an index. The following command prints the current

PATH :

puts "$env(PATH)"








Secret


You can manipulate the environment variable array,

env , just as you do any other variables. You can add a new directory to

PATH , for example, as follows:

set env(PATH) "$env(PATH):/usr/sbin"

Any changes to the environment variable do not affect the parent process (for example, the shell from which you start the Tcl script). Any new processes the script creates by means of the

exec command, however, inherit the altered environment variable.












Performing File Operations in Tcl


Most of the examples presented so far in this chapter use Tcl's

puts command to display output. By default,

puts writes to the standard output, the terminal window or text console, when you use X. You can write to a file, however, by providing a file identifier as the first argument of

puts . To get a file identifier, you first have to open the file by using Tcl's

open command. The following example shows how you open a file, write a line of text to the file, and close the file (in this example

fid is a variable that stores the file identifier):

set fid [open "testfile" w]  ;# Open "testfile" for writing
puts $fid "Testing 1..2..3" ;# Write to this file
close $fid ;# Close the file

When you use

puts to display a string on the standard output, you do not have to provide a file-identifier argument. In addition,

puts automatically appends a newline character to the end of the string. If you do not want the newline, use

puts with the

-nonewline argument, as follows:

puts -nonewline "Command> "  ;# This is good for command prompts.
flush stdout ;# Make sure output appears right away

You have seen the use of the

gets command to read a line of input from the standard input. The following invocation of

gets , for example, reads a line from the standard input (the command returns when you press Enter):

set line [gets stdin]  ;# Read a line from standard input.

The keyword

stdin is a predefined file identifier that represents the standard input, which by default is your keyboard. Other predefined file IDs are

stdout , for the standard output; and

stderr , for the standard error-reporting device. By default, both

stdout and

stderr are connected to the display screen.

Following is a different way to call

gets and read a line of input into a variable named

line :

gets stdin line  ;# Read a line of input into the line variable

To read from another file, you should open the file for reading and then use

gets with that file's ID. To read all lines from

/etc/passwd and display them on the standard output, for example, use the following:

set fpass [open "/etc/passwd" r]     ;# Open /etc/passwd. 
while { [gets $fpass line] != -1} { ;# Read the lines one by one
puts $line ;# and print each line.
}

The

gets command is good for reading text files because it works one line at a time; in fact, it looks for the newline character as a marker that indicates the end of a line of text. If you want to read binary data, such as an image file, use the

read command instead. To read and process a file in 2,048-byte chunks, you might use read in the following manner:

# Assume fid is the file ID of an open file.
while { ![eof $fid]} { ;# Until end-of-file is reached
set buffer [read $fid 2048] ;# read 2048 bytes into buffer
# process the data in buffer ;# and process the buffer.
}

The second argument of the

read command is the maximum number of bytes to be read. If you omit this argument, the

read command reads the entire file. You can use this feature to process entire text files. After reading the contents of the file, use the

split command to separate the input data into lines of text. Following is an example:

set fid [open "/etc/passwd" r] ;# Open file for reading
set buffer [read $fid 100000] ;# Read entire file into buffer
split $buffer "\n" ;# Split buffer into lines
foreach line $buffer {
puts $line ;# Process each line.
}








Secret


If you want to process several files (such as all files whose names end with

.tcl ), use the

glob command to expand a filename, such as

*.tcl , into a list. Then, you can use the

open command to open and process each file in the following manner:

foreach filename [glob *.tcl] { ;# Create list of filenames
puts -nonewline $filename ;# Print the filename.
set file [open $filename r] ;# Open that file.
gets $file line ;# Read the first line
puts $line ;# and print it (for testing).
# process rest of the file as necessary
close $file ;# Remember to close the file.
}

This is a good example of how to use the

glob command in a script.












Executing Linux Commands in Tcl


Instead of duplicating the large number of Linux commands, Tcl simply provides the mechanism to run any Linux command. If you know Linux commands, you can use them directly in Tcl scripts.

Use the

exec command to execute a Linux command in a Tcl script. In the command's simplest form, you provide the Linux command as an argument of exec. To show the current directory listing, for example, type the following:

exec ls

The output appears on the standard output (the monitor), just as it does when you enter the

ls command at the shell prompt.

When you run Linux commands from the shell, you can redirect the input and output by using special characters, such as < (redirect input), > (redirect output), and

| (pipe). These options are available in Tcl as well; the

exec command accepts a complete command line, including any input or output redirections. Thus, you can send the directory listing to a file named

dirlist as follows:

exec ls > dirlist








Secret


Tcl's

exec command does not expand wildcard characters (such as an asterisk or a question mark) in filenames passed to a Linux command. If you use wildcards in filenames, you have to perform an additional step: You must process the filename specification through the

glob command to expand it properly before providing the command to

exec . In addition, you must pass the entire

exec command to

eval as an argument. To see a list of all files with names that end in

.tcl , for example, you have to use the

exec command with

glob and feed the entire command to

eval as follows:

eval exec ls [glob *.tcl]   ;# this is equivalent to "ls *.tcl"












/ 341