Pages

Sunday, May 6, 2012

TCL Tips & Tricks!!!

Q.1- How can I create/use association lists or property lists?
Use arrays or Extended Tcl keyed lists.
For example, if you did a:
    keylset ttyFields ttyName tty1a
    keylset ttyFields baudRate 57600
    keylset ttyFields parity strip
And then an echo $ttyFields, you'd get:

    {ttyName tty1a} {baudRate 57600} {parity strip}
Or using arrays:

    set ttyFields(ttyName)  tty1a
    set ttyFields(baudRate) 57600
    set ttyFields(parity)   strip

Q.2 - How can I generate a random number in Tcl?
Tcl 8.0 includes a random number generator as a function in the expr command (one is also available in Extended Tcl as a standalone command and has been for
quite a while).
For example, to generate a random number between 0 and 9 inclusive:
    set random_number [expr int(rand()*10)]

Q.3 - How can I pass an array into a proc?
Use upvar rather than try to use global variables when possible. If the function is event driven, you are forced to use global variables.

    # print elements of an array
    proc show_array arrayName {
        upvar $arrayName myArray

        foreach element [array names myArray] {
           puts stdout "${arrayName}($element) =  $myArray($element)"
        }
    }

    set arval(0) zero
    set arval(1) one
    show_array arval
To return an array from a procedures, just take the array name in as an argument, as above. Any changes you make in the array will be made in the parent's
array as well.

Extended Tcl introduces a concept called keyed lists which are arrays made out of lists of key-value pairs and can be passed by value to routines, over
networks, etc.

Q.4 - How can I delete a procedure from within a script?
Rename the procedure to have no name, for example:
    rename procedureName ""

Q.5- How can I do a double indirect? - Why doesn't $$var work?
There is one and only one level of substitution possible with every pass through the interpreter.Also, when doing variable substitution, the interpreter
finds the dollar sign and then takes everything following it up until the next invalid character (where invalid is defined as anything other than a letter,
digit, or underscore) as the name of the variable - well, that is, unless it finds array notation or the ${varname} form.

In the case of $$var, the character after the first dollar sign is an invalid character (another dollar sign), so there is no variable name and variable
substitution is not performed (the dollar sign is left as is) and scanning starts again for any dollar signs and the following variable name. It is immediately
found at that second dollar sign, the substitution is performed, and scanning for dollar signs resumes with whatever was after the variable name. Since there
isn't anything else, substition is done for this pass through the interpreter (remember it's only done once).

The eval command runs its arguments through the interpreter, so you could use eval to cause the second pass through the interpreter, and thus, have $$var work:

    % set a 5
    5
    % set var a
    a
    % puts $$var              ;# This doesn't work
    $a
    % eval puts $$var         ;# This does  - but it's dangerous
    5
However, if the contents of var contain any special characters (e.g. whitespace, semicolon) you'll run into problems.

A better method is to take advantage of the behavior of the set command when given only one argument, and combine command substitution with variable
substitution:

    % puts [set $var]         ;# This works safely
    5
or, in fact, you could use just command substitution (which is performed once for each [ ] pair):

    % puts [set [set var]]    ;# as does this
    5
Similarly, to print the values of var1, var2, and var3:

    set var1 3.14159
    set var2 hello
    set var3 13
    foreach num {1 2 3} {
                puts "var$num = [set var$num]"
    }
will output:

    var1 = 3.14159
    var2 = hello
    var3 = 13
The upvar command can also be used to derefence variables.

Q.6- How can I perform a non-blocking read on a file identifier?
    read $fileId [fstat $fileId size]
This will read only the number of bytes currently available on fileId and consequently will not block.

Q.7 - How can I find what version I am running?
Well, there is no one answer to this. Tcl itself, will tell you its version, if you type:
    puts $tcl_version
or in older versions:
    info tclversion
To get the Tk version, use:

    puts $tk_version
Other extensions use other means (for example, Extended Tcl uses infox version to return its version number).

Starting with the 7.4 version, the tclsh executable is, by default, installed with the version number appended - making it rather obvious which version you
are running. However, if it is not installed like that on your system, you can find out the version from the shell prompt with something like:

    echo 'puts $tcl_version;exit 0' | tclsh
(the ;exit 0 part is only needed for wish and its derivatives, but doesn't hurt anything when it isn't needed)

Q.8- How can I use variables to hold array names?
You may have written something like:
    % set foo "bar baz"
    bar baz
    % foreach aap $foo {
        set $aap(1) "something"
    }
    can't read "aap(1)": variable isn't array
This means Tcl tries to substitute the array element aap(1) which doesn't exist. To fix this use:

    % foreach aap $foo {
        set [set aap](1) "something"
    }
In this case two arrays bar and baz are created.

An alternative format is:

    % foreach aap $foo {
        set ${aap}(1) "something"
    }

Q.9 - How can I convert between a character and its ASCII value?
To get the ASCII value of a character:
    proc toASCII { char } {
        scan $char %c value
        return $value
    }
    puts "The ASCII value of 'A' is [toASCII A]"
To convert from an ASCII value to a character:

    proc toChar { value } {
        return [format %c $value]
    }

    puts "The ASCII value 65 corresponds to the character '[toChar 65]'"

Q.10- "not found" or "Command not found"
This error message comes from your shell, not Tcl. The script probably starts with a #! that is followed by a path to the Tcl interpreter that is too long
for your system. Many Unix systems are limited to 32 characters (including the #!) in this regard. So, something like this will fail:

    #! /usr/home/homedir/very/long/path/tclsh

    # rest of script
You can either shorten the path by moving the tclsh executable to a different directory or by using symbolic links. Another option is to not specify the path
at all. See the question "How do I make my script executable regardless of the location of tclsh?" for an example of how to do this.

Q.11- How do I make my script executable regardless of the location of tclsh?
There are several tricks you can use, but the most common is to make use of the fact that, in Tcl, the backslash character works as a line continuation
indicator, even within comments. So instead of:
    #! /usr/local/bin/tclsh
    puts "Hello World"
You could use:

    #! /bin/sh
    # The next line is executed by /bin/sh, but not Tcl \
      exec tclsh $0 ${1+"$@"}

    puts "Hello World"
and the script will run regardless of where tclsh is located (as long as it is in one of the directories in the user's PATH).

==============================

What Tcl refers to as an array has other names in other languages. Awk calls them associative arrays and some language (Perl?) calls them hash maps. In
Python, dictionaries are pretty much the same.
The reason this is an important concept up front is that Tcl does not provide a simple numerically indexed array in the traditional sense. Instead, the index
for a Tcl array is a Tcl string.
Tcl arrays are one dimensional. However,if you are careful you can simulate a multi-dimensional array like this:
 for {set i 0} {$i < 10} {incr i} {
   for {set j 0} {$j < 10} {incr j} {
     set a($i,$j) "Value for i = $i and j = $j"
     puts "$a($i,$j)"
   }
 }
Note however that "$i,$j" is parsed into a string that differs from the string "$i, $j" for instance -- it is best never to put blanks in the text of your
array keys.
Also, for this type of application, it is much better to use integer values for i and j rather than characters. Otherwise, as in the previous point, you
might run into cases where whitespace varies within the values of i and j, resulting in missed values.
Note that if you really do want to have spaces (or other Tcl-significant characters) in your array indexes, you can still do this by putting the index into a
variable and then using the dereferenced variable as your index:
   % set idx "The quick brown fox"
   % set ary($idx) "jumped over the lazy dogs."
   % parray ary
   ary(The quick brown fox) = jumped over the lazy dogs.
You can even have the name of the array with a space in, but accessing it then takes the application of an [upvar] to convert to a more usable form... or
just backslashes: set foo\ bar(baz\ grill) 1
You can also include whitespace characters in a key by quoting the entire argument with double quotes:
    % set capital(New Mexico) "Santa Fe"
    wrong # args: should be "set varName ?newValue?"
    % set "capital(New Mexico)" "Santa Fe"
    Santa Fe
    % puts "$capital(New Mexico)"
    Santa Fe
    %
Of course, it's still best to avoid whitespace characters in keys whenever possible...

=======
The TclX extension also has a construct called keyed lists. Here's an example:
    keylset ttyFields ttyName tty1a
    keylset ttyFields baudRate 57600
    keylset ttyFields parity strip
Then when you would type
    echo $ttyFields
you would see:
    {ttyName tty1a} {baudRate 57600} {parity strip}
Using arrays, one would set things up as:
    set ttyFields(ttyName)  tty1a
    set ttyFields(baudRate) 57600
    set ttyFields(parity)   strip

=============
RegExp tricks edit

Regular expressions are expensive to compile, and non-constant regexps must be compiled every time they are scanned for.
Suppose you want to check for the case where there is "a b c" with arbitrary (including none) amounts of whitespace between the letters. In 8.0, the
following is the most obvious way to do it, but it is hard to write:
    regexp "a\[ \t\n\r\]*b\[ \t\n\r\]*c\[ \t\n\r\]" $string
For clarity's sake it is far better to do:
    set ws "\[ \t\n\r\]"
    regexp "a${ws}*b${ws}*c" $string
However, this is not very efficient since it forces recompilation each time (unlike the first version where the string is constant, and therefore can support
Tcl_Obj-based saving of compiled values.) The following does not suffer from this problem, and is probably clearer as well in practical programs:
    # Only execute these lines once, at startup time
    set ws "\[ \t\n\r\]"
    set abcRE "a${ws}*b${ws}*c"

    # Now refer to the (probably global) variable each time you want to match
    regexp $abcRE $string
If you are using 8.1 or later, you have access to the new regular expression engine, which allows several things to make this bite less (special escapes for
common sequences, regular expression cache (in later versions), and implemented cacheing of REs in Tcl_Objs...)
The best solution for our example problem is probably
    set pat {a\s*b\s*c}    ;# Globally

    regexp $pat $string    ;# Each time needed
(See comment below for additional speedup.)
In general, do whatever you can to avoid
Solution: We need to change the 8.1 implementations to introduce a second level cache similar to the one in 8.0. This will allow us to avoid recompilation in
cases where the same computed string value is passed in, even when it comes from a different object. We can probably use a thread-local cache, instead of a
per-interp cache to improve sharing and make the regexp code more modular.
Actually, for performance sake, the best solution is to inline the pattern:
    regexp {a\s*b\s*c} $string
This will be even faster (yes, I've verified this with timings). For simple regexps, this is more readable anyway since it keeps the regexp definition where
it is being used.
Another significant way to speed up regular expressions is to avoid making the regexp retry matches (i.e., backtrack) if possible. As a simple case, consider
this:
  regexp {a.*b.*c} "abbbbbbbbbbbbbbbbbbbb"
In this statement, the regexp engine is going to match the "a", then the "b" and then fail to match the "c". But it won't stop there, it will match every
single b and using those matches will try (and fail to match the c in every position (where there are b's)). This is extremely inefficient. It is much more
efficient to break this into to two searches so that you can prevent the regexp engine from all the pointless work backtracking.
This is just the tip of the iceberg, alas.
I think the above backtrack issue went away with the updated 8.1+ RE, but the problem does still exist in 8.4.16/8.5b2 for the equivalent glob case:
  string match "*a*b*c*" "abbbbbbbbbbbbbbbbb"
That you end up with pointless backtracking.

======================
Keyed lists
Keyed lists provide a structured data type built upon standard Tcl lists. This provides a functionality similar to structs in the C programming language.

A keyed list is a list in which each element contains a key and value pair. These element pairs are stored as lists themselves, where the key is the first
element of the list, and the value is the second. The key-value pairs are referred to as fields. This is an example of a keyed list:

   {{NAME {Frank Zappa}} {JOB {musician and composer}}}
If the variable person contained the above list, then keylget person NAME would return {Frank Zappa}. Executing the command:

keylset person ID 106
would make person contain:

   {{ID 106} {NAME {Frank Zappa}} {JOB {musician and composer}}
Fields may contain subfields; ``.'' is the separator character. Subfields are actually fields where the value is another keyed list. Thus, the following list
has the top level fields ID and NAME, and subfields NAME.FIRST and NAME.LAST:
   {ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}
There is no limit to the recursive depth of subfields, allowing you to build complex data structures.
Keyed lists are constructed and accessed by a number of commands. All keyed list management commands take the name of the variable containing the keyed list
as an argument (that is, passed by reference), rather than passing the list directly.

Available commands are:

keyldel listvar key
          Delete the field specified by key from the keyed list in the
          variable listvar.  This removes both the key and the value
          from the keyed list.
keylget listvar ?key? ?retvar | {}?
          Return the value associated with key from the keyed list in
          the variable listvar.  If retvar is not specified, then the
          value will be returned as the result of the command. In this
          case, if key is not found in the list, an error will result.

          If retvar is specified and key is in the list, then the
          value is returned in the variable retvar and the command
          returns 1 if the key was present within the list.  If key
          isn't in the list, the command will return 0, and retvar
          will be left unchanged.  If {} is specified for retvar, the
          value is not returned, allowing the Tcl programmer to
          determine if a key is present in a keyed list without setting a
          variable as a side-effect.

          If key is omitted, then a list of all the keys in the keyed
          list is returned.
keylkeys listvar ?key?
          Return the a list of the keys in the keyed list in the
          variable listvar.  If keys is specified, then it is the name of
          a key field  who's subfield keys are to be retrieve.
keylset listvar key value ?key2 value2 ...?
          Set the value associated with key, in the keyed list
          contained in the variable listvar, to value.
          If listvar does not exists, it is created.
          If key is not currently in the list, it will be added.
          If it already exists, value replaces the existing value.
          Multiple keywords and values may be specified, if desired.
==========================================

How do I convert a list into string in Tcl?
set list {a b c d e f}
for {set i 0} {$i<[llength $list]} {incr i} {
    append string [lindex $list $i]
}
puts $string

======================================
How to remove {} from below expression?
set y "Interface {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} IP-Address {} {} {} {} {} OK? Method Status {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}
{Protocol FastEthernet0/0} {} {} {} {} {} {} {} {} {} {} {} unassigned {} {} {} {} {} YES unset {} administratively down down {} {} {} {FastEthernet0/1} {}
{} {} {} {} {} {} {} {} {} {} unassigned {} {} {} {} {} YES unset {} administratively down down"

set y [regsub -all ({}\ )+ $y ""]

======================================
How to unpack a list into variables in Tcl?
foreach {a b c} {1 2 3} {break}

puts $a
puts $b
puts $c

====================================
How can I redirect stdout into a file in tcl
proc foo {fp} {
   puts $fp "some text"
}

set fp [open bar w]
foo $fp
close $fp

=========================================
Parsing a file with Tcl
set f [open $filename]
while {[gets $f line] > -1} {
    # Process lines
    if {[regexp {^set +(\S+) +(.*)} $line -> name value]} {
        puts "The name \"$name\" maps to the value \"$value\""
    }
}
close $f

==========================================
How do I force conversion of a string into a list?
Quick answer: Use the split command.

========================================
How can I tell the difference between a string and a list?
Data structures in Tcl cannot rely on distinguishing between strings and single-element lists. If this is important in your application, you will need to
include some extra flag information in the data structure to distinguish the two cases.

==========================================
TCL arrays

Tcl arrays are collections of variables, rather than values. This has advantages in some situations (e.g., you can use variable traces on them), but also has
a number of drawbacks:

They cannot be passed directly to a procedure as a value. Instead you have to use the array get and array set commands to convert them to a value and back
again, or else use the upvar command to create an alias of the array.
Multidimensional arrays (that is, arrays whose index consists of two or more parts) have to be emulated with constructions like:
set array(foo,2) 10
set array(bar,3) 11
The comma used here is not a special piece of syntax, but instead just part of the string key. In other words, we are using a one-dimensional array, with
keys like "foo,2" and "bar,3". This is quite possible, but it can become very clumsy (there can be no intervening spaces for instance).
Arrays cannot be included in other data structures, such as lists, or sent over a communications channel, without first packing and unpacking them into a
string value.

===========================================
TCL Lists and Arrays
TCL has many facilities for manipulating lists, which are collections of items separated by whitespace. For example, "llength" returns the number of items in
a list, "lindex" returns the Nth item in a list starting at item 0, "lrange" returns a range of items from a list, and "lsearch" returns the location of a
list item that matches a given value:

% set days "Mon Tue Wed Thu Fri Sat Sun"
Mon Tue Wed Thu Fri Sat Sun
% llength $days
7
% lindex $days 0
Mon
% lindex $days 1
Tue
% lrange $days 3 5
Thu Fri Sat
% lrange $days 5 end
Sat Sun
% lsearch $days Wed
2

The variables we have seen so far are examples of TCL "scalar" variables, which store a single text value. The text value might be a single numeric item, or
a whitespace-separated collection of items of any length TCL also includes associative arrays which allow many values to be assigned to a variable
according to an array index. In the case of many programming languages such as C, an array index will be one or more integer numbers. However in TCL, the
array index can be any text value.This is a powerful feature for organizing data, and it also allows us to simulate the use of conventional
multidimensional arrays in TCL.

TCL array variables are specified by an array name and an array index in ( ) parenthesis.As noted, the array index can be any text value, numeric or
otherwise. The assigned value can also be any text value, numeric or otherwise For example:

set monthInfo(1) Jan
set monthInfo(2) Feb

set dayInfo(30) "Sep Apr Jun Nov"
set dayInfo(31) "Jan Mar May Jul Aug Oct Dec"
set dayInfo(28) "Feb"

set mass(H) 1.0
set mass(He) 4.0
set mass(C) 13.0

Values of an array variable are extracted using $ dollar-sign substitution, as with scalar variables. The interesting detail is that the array index ca
also be specified in terms of a TCL expression. So, given the definitions above, from the nmrWish command line:

% puts $dayInfo(30)
Sep Apr Jun Nov

% puts $monthInfo([expr 1 + 1])
Feb

% set atom He
He
% puts $mass($atom)
4.0

To simulate a conventional multidimensional array, we can use a TCL array index composed of one or more integers, usually separated by a character such as
the "," comma.For example, we can build an array index which simulates a three-dimensional matrix location, by using three integer values to create the
index:

set ix 0
set iy 0
set iz 0
set a($ix,$iy,$iz) 1.14

Note again that the TCL array index is interpreted as an exact text value, not as a numeric one.So, space characters, decimal points, etc., change the
interpretation of the array index. In the example above, the array index is the exact five-character text value "0,0,0"for another example, the
following cases all refer to different array elements:

$m(1)
$m(1.0)
$m(1.00)
$m( 1)
$m(001)

The standard TCL command "info exists" can be used to test whether or not a given array value has been defined.

====================================================
Tip #1 Use {} braces to isolate a variable in a longer a string.
If I have a variables for  process, voltage, and temperature.

set process 1.0
set voltage 0.8
set temperature -40

And I want to create a file name with the process, voltage, and temperature embedded in it along with the units V and C.
Here’s one way:

set filename library_${process}_${voltage}V_${temperature}C.lib

Note how the curly braces are used to wrap process, voltage, and temperature variables. No tricky escaping or temporary
variables needed.

Use foreach to break apart a list in to its components.
In this example I’m working with a description of a temperature range. I’m told the description is a list that starts with the
initial temperature, the middle value is the final temperature, and the last value is the step size between them.

set range [list -30 15 5]
If I want to write a script that enumerates all the temperatures in the range. I’m going to need to get each value from the
list separately.  Typically, accessing individual elements of the list is done with Tcl’s lindex command.  However, a clever
one-liner every once in a while can be really useful.

foreach {initial_value final_value step_size} $range break
The break at the end ensures that if range happened to be a longer list we’d only grab the 1st set of values.

Here’s an example procedure that enumerates all the temperatures.

# get the temperatures in the given range
proc get_temperatures { range } {
    foreach {initial_value final_value step_size} $range break

    set temperatures [list]
    for { set t $initial_value } { $t <= $final_value } { incr t $step_size } {
        lappend temperatures $t
    }

    # make sure the final temperature is included even if the step size was too big to include it
    if { [lindex $temperatures end] != $final_value } {
        lappend temperatures $final_value
    }
    return $temperatures
}
Tcl’s foreach is a very versatile command. No doubt, we’ll use it again.

Here are examples of TCL commands that I use repeatedly.

# create a tool version
set version 0.02
puts "JPVINFO: makeViews version: $version"

# use time for file timestamps
set viewsDate [exec date "+%H:%M:%S_%m_%d_%Y"]
puts "JPVINFO: view generation complete: $viewsDate"

# list files in the run directory
puts [glob *]

# create a path for use by commands
set makeViewsPath /home/jvogel/design/tclWork/makeViews
source $makeViewsPath/makeViewsProcs.tcl

# check for a missing file
if ![file exist ./makeViewsData.txt] { JPVnoDesignDataFile }

# check for existence of a file
if [file exist $moduleName.v] { exec mv $moduleName.v $moduleName.v_old_$viewsDate }

# using a seperate global variables file called by each process
proc JPVbuildViews {} {
 global makeViewsPath ;
 source $makeViewsPath/makeViewsGlobals.tcl
... }

# read a data file and parse the contents
set fin [open ./makeViewsData.txt r]
while {[gets $fin line] >= 0} {
    # get rid of those nasty multiple spaces...
    regsub -all -- {[[:space:]]+} $line " " line
    set lineList [split $line " "]
    set listLength [llength $lineList]
    set firstArg [lindex $lineList 0]
   if [regexp -nocase {^#} $firstArg] then {
            if [expr $DEBUG == "TRUE"] { puts "// $lineList" }
    } elseif [regexp -nocase {module} $firstArg] then {
            set moduleName [lindex $lineList 1]
    } elseif [regexp -nocase {clock} $firstArg] then {
           lappend clockList [lindex $lineList 1]
           lappend inputList [lindex $lineList 1]
   }
  }
close $fin

# write to a file
set fout [open $moduleName.v w]
puts $fout "module $moduleName ("
foreach i $outputList { puts $fout ",$i" }

# using two lists with indexing to select matched values
set j 0
foreach i $paramList {
  puts $fout "parameter $i \= [lindex $paramValues $j] ;"
  incr j
}

# insert a header file at the top of a verilog file
set fin [open $makeViewsPath/makeViewsHeader.txt r]
while {[gets $fin line] >= 0} { puts $fout "//$line"}
close $fin

# insert a header file at the top of a tcl file
set fin [open $makeViewsPath/makeViewsHeader.txt r]
while {[gets $fin line] >= 0} { puts $fout "#$line"}
close $fin

TCL Question Answer

WHAT IS TCL?
Tcl (Tool Command Language from Sun Microsystems) is a very powerful but easy to learn dynamic programming language, suitable
for a very wide range of uses, including web and desktop applications, networking, administration, testing and many more. Open
source and business-friendly, Tcl is a mature yet evolving language that is truly cross platform(windos,all flavors of
linux,macintosh), easily deployed and highly extensible.
Developer :Ousterhout

How to Swap 30 & 40 in IP address 192.30.40.1 using TCL script?
There are three solutions.

set a 192.30.40.1
set b [ string range $a 3 4 ]
set c [ string range $a 6 7 ]
set d [ string replace $a 3 4 $c ]
set e [ string replace $d 6 7 $b]
puts $e

#=====OR=====
set a 192.30.40.1
set b [ split $a .]
set u [lindex $b 0]
set v [lindex $b 3]
set x [lindex $b 1]
set y [lindex $b 2]
set z [join "$u $y $x $v" .]
puts $z

#====OR======
set ip 192.30.40.1
regexp {([0-9]+\.)([0-9]+\.)([0-9]+\.)([0-9]+)} $ip match 1st 2nd 3rd 4th
append newIp $1st $3rd $2nd $4th
puts $newIp

How do you find the length of a string without using string length command in TCL??
set str "lenghtofthisstring"; set len 0
set list1 [ split $str "" ]
foreach value $list1 {
incr len
}
puts $len

#======OR======

set str "lenghtofthisstring"
puts [llength [ split $str "" ]]

How do you check whether a string is a palindrome or not using TCL script?
#gets stdin a
set a malayalam
set len [ string length $a ]
set n [ expr $len/2 ]

for { set i 0 } { $i < $n } { incr i 1 } {
set b [ string index $a $i ]
set c [ expr $len - 1 - $i ]
set d [ string index $a $c ]

if {$b != $d} {
puts "not a palindrome"
exit

}
}
puts "Palindrome"
#======OR======

#gets stdin a
set a madam
set len [ string length $a ]
set n [ expr $len/2 ]

for { set i 0 } { $i < $n } { incr i 1 } {
set b [ string index $a $i ]
set c [ expr $len - 1 - $i ]
set d [ string index $a $c ]

if {$b != $d} {
puts "not a palindrome"
exit

}

}
puts "Palindrome"

Set ip address as 10.30.20.1 write a script to replace the 30 with 40 ?
set ip 10.30.20.1
regsub -all {30} $ip {40} ip
puts $ip

#========OR===============
set a 10.30.2.1
set b [ string replace $a 3 4 40 ]
puts $b
  
----------------------------------------------------------------------------------------------------------------
$ causes variable substitution.

[ ] causes command substitution.

“ " quotes white space and semi-colons.

Double-quotes disable word and command separators, while braces disable almost all special characters.

Quoting with double-quotes: If a word is enclosed in “”, then spaces, tabs & ; are treated as ordinary characters.

       e.g. set msg "Eggs: \$2.18/dozen\nGasoline: \$1.49/gallon"

=> Eggs: $2.18/dozen

Gasoline: $1.49/gallon

     Note: Within “” quotes all previous substitutions occurs as usual

Quoting with braces: Curly braces prevent breaks and substitutions. Braces provide a more radical form of quoting where all
the special characters lose their meaning. If a word is enclosed in braces then the characters between the braces are the
value of the word, verbatim. No substitutions are performed on the word and spaces, tabs, newlines, and semi-colons are
treated as ordinary characters.

  e.g. set msg {Eggs: $2.18/dozen\nGasoline: $1.49/gallon}

=> Eggs: $2.18/dozen\nGasoline: $1.49/gallon
----------------------------------------------------------------------------------------------------------------

Procedures
If the last argument in the argument list has the special name args, procedure takes varying number of arguments

If no extra arguments, args will be set to an empty string

Example:-
proc sum args {
set s 0
foreach n $args {
incr s $n
}
return $s
}
Here sum can be invoked with different number of arguments,   as follows:
sum 1 2 3 4 5
=> 15
sum
      => 0


If the arguments before args are defaulted then there should not be an extra argument, so args will be set to an empty string

No defaults can be specified for args (the empty string is the default)

----------------------------------------------------------------------------------------------------------------
package require Tnm

namespace import Tnm::*

proc walk {} {

set handle [snmp generator -address localhost]

set var 1.2.1

set val 0

while {1} {

set var [snmp oid [$handle getnext $var]]

puts "$var\t[mib name $var]\t\t[snmp value [$handle get $var]]"

if {$val==$var} {

break

} else {

set val $var

}

}

}

#################AnOther way

proc awalk {} {

set handle [snmp generator -address localhost]

set var mib-2

set val 0

while {1} {

set var [snmp oid [$handle getnext $var]]

puts "$var\t[mib name $var]\t\t[snmp value [$handle get $var]]"

if {$val==$var} {

break

} else {

set val $var

}

}

}

########################Another way
proc mwalk {} {

set handle [snmp generator -address localhost]

set var mib-2

set val 0

while {![regexp "endOfMibView" $var]} {

set var [snmp oid [$handle getnext $var]]

puts "$var\t[mib name $var]\t\t[snmp value [$handle get $var]]"

if {$val==$var} {

break

} else {

set val $var

}

}

}


How does one set an array member value?

set array("key") "123xyz"

-------------------------------------------------------------------------------
What is a Tcl array?
A Tcl array is similar to what other languages call a hash or an associated array. It is a data structure that allows one to
associate an array member index (aka array key) with an array member value. The array member index can be any legal Tcl
string. The array member value can be any legal Tcl string.

------------------------------------------------------------------------------------
Write a Procedure to sum two numbers with one variable has a default value.
proc sum {a {b 5}} {
set c [expr $a+$b]
puts $c
}

sum 1

 --------------------------------------------------------------------------------------------------------------
Create an array in TCL
Set var_name(0) 1
Set var_name(1) 2
Set var_name(2) 3
-------------------------------------------------------------------------------------------

Write a Procedure to sum two numbers
proc sum {a b} {
set d [expr $a+$b]
puts $d
}

sum 5 1

-------------------------------------------------------------------------------------------

Concatenate

This command treats each argument as a list and concatenates them into a single list. It also eliminates leading and trailing
spaces in the arg's and adds a single separator space between arg's. It permits any number of arguments.  For example, the
command

concat a b {c d e} {f {g h}}

a b c d e f {g h}

If no args are supplied, the result is an empty string. 

-------------------------------------------------------------------------------------------

Write a TCL script to open a file in write mode

set fid [open new_file.txt w]

-------------------------------------------------------------------------------------------

Debugging in TCL

To see where the error was triggered in interactive mode, use errorInfo

proc a {} {

global errorInfo

puts hi

}

a

This variable shows index of the faulty line inside the procedure body info body _the_name_of_the_procedure_

info body a
-------------------------------------------------------------------------------------------

Write a TCL script to open a file in read mode

set fid [open new.txt r]

r Open the file for reading only; the file must already exist. This is the default value if access is not specified.
-------------------------------------------------------------------------------------------

#Script to get only two characters

puts "Enter any two characters"

set x [read stdin 2]

puts $x

#Script to accept any characters

puts "Enter any characters"

set y [gets stdin]

puts $y

#Script to accept any characters

puts "Enter any characters"

gets stdin z

puts $z

-------------------------------------------------------------------------------------------

proc sting rev {

set i [string length $rev]

set rs ""

while {$i >0} {

append rs [string index $rev [incr i -1]]

}

set i [string length $rev]

set k 0

for {set j 0} {$j<=$i} {incr j} {

puts -nonewline "$j\t"

set d [string index $rev $j]

set e [string index $rs $j]

puts "$d $e"

if {$d==$e} {

incr k

}

}

if {$k>$i} {

puts Palindrome

}

return $rs

}

sting madam

sting malayalam

sting netprowise

-------------------------------------------------------------------------------------------

How do you find the length of a string without using string length command in TCL?

set len 0

set str "lenghtofthisstring"

set list1 [ split $str "" ]

foreach value $list1 {

incr len

}

puts $len

======================

set str "lenghtofthisstring"

puts [llength [ split $str "" ]]

===========================





1 comment:

  1. Hi, I read your blogfs daily. Your humoristic style is awesome, keep
    up the good work!
    http://www.dailyblogzone.com

    ReplyDelete