Jacl is an alternate implementation of TCL, and is written entirely in Java code.
The wsadmin tool uses Jacl V1.3.1.
Basic syntax:
Command arg1 arg2 arg3 ...The command is either the name of a built-in command or a Jacl procedure. For example:
puts stdout {Hello, world!} => Hello, world!In this example, the command is puts which takes two arguments, an I/O stream identifier and a string. The puts command writes the string to the I/O stream along with a trailing new line character. The arguments are interpreted by the command. In the example, stdout is used to identify the standard output stream. The use of stdout as a name is a convention employed by the puts command and the other I/O commands. stderr identifies the standard error output, and stdin identifies the standard input.
Variables
set a 5 => 5
set b $a => 5The second example assigns the value of variable a to variable b. The use of dollar sign ($) is indicates variable substitution. You can delete a variable with the unset command, for example:
unset varName1 varName2 ...You can pass any number of variables to the unset command. The unset command will give error if a variable is not already defined. You can delete an entire array or just a single array element with the unset command. Using the unset command on an array is a easy way to clear out a big data structure. The existence of a variable can be tested with the info exists command. You may have to test for the existence of the variable because the incr parameter requires that a variable exist first, for example:
if ![info exists foobar] {set foobar 0} else {incr foobar}
Command substitution:
set len [string length foobar] => 6In this example, the nested command is the following: string length foobar. The string command performs various operations on strings. In this case, the command asks for the length of the string foobar. If there are several cases of command substitution within a single command, the interpreter processes them from left bracket to right bracket. For example:
set number "1 2 3 4" => 1 2 3 4
set one [lindex $number 0] => 1
set end [lindex $number end] => 4
set another {123 456 789} => 123 456 789
set stringLen [string length [lindex $another 1]] => 3
set listLen [llength [lindex $another 1] => 1
Math expressions:
expr 7.2 / 3 => 2.4
Backslash substitution:
set dollar "This is a string \$contain dollar char" => This is a string $contain dollar char set x $dollar => This is a string $contain dollar char set group {$ {} [] { [ } ]} => $ {} [] { [ } ]You can also use backslashes to continue long commands on multiple lines. A new line without the backslash terminates a command. A backslashes that are the last character on a line convert into a space. For example:
set totalLength [expr [string length "first string"] + \ [string length "second string"]] => 25
Grouping with braces and double quotes:
set s Hello => Hello puts stdout "The length of $s is [string length $s]." => The length of Hello is 5. puts stdout {The length of $s is [string length $s].} => The length of $s is [string length $s].In the second example, the Jacl interpreter performs variable and command substitution on the second argument from the puts command. In the third command, substitutions are prevented so the string is printed as it is.
Special care must also be taken with path descriptions
because the Jacl language uses the backslash character (\) as an escape
character. To fix this, either replace each backslash with a forward
slash, or use double backslashes in distributed path statements. For
example: C:/ or C:\\
Procedures and scope:
proc name arglist bodyThe first argument is the name of the procedure being defined. The name is case sensitive, and in fact it can contain any characters. Procedure names and variable names do not conflict with each other. The second argument is a list of parameters to the procedures. The third argument is a command, or more typically a group of commands that form the procedure body. Once defined, a Jacl procedure is used just like any of the built-in commands. For example:
proc divide {x y} { set result [expr $x/$y] puts $result }Inside the script, this is how to call devide procedure:
divide 20 5And it will give the result like below:
4It is not really necessary to use the variable c in this example. The procedure body could also written as:
return [expr sqrt($a * $a + $b * $b)]The return command is optional in this example because the Jacl interpreter returns the value of the last command in the body as the value of the procedure. So, the procedure body could be reduced to:
expr sqrt($a * $a + $b * $b)The result of the procedure is the result returned by the last command in the body. The return command can be used to return a specific value.
global varName1 varName2 ...
Comments
Use the pound character (#) to make comments.
Command line arguments
set first [lindex $argv 0] set second [lindex $argv 1]
Strings and pattern matching
string operation stringvalue otherargsThe operation argument determines the action of the string. The second argument is a string value. There may be additional arguments depending on the operation.
Command | Description |
string compare str1 str2 | Compares strings lexicographically. Returns 0 if equal, -1 if str1 sorts before str2, else1. |
string first str1 str2 | Returns the index in str2 of the first occurrence of str1, or -1 if str1 is not found. |
string index string index | Returns the character at the specified index. |
string last str1 str2 | Returns the index in str2 of the last occurrence of str1, or -1 if str1 is not found. |
string length string | Returns the number of character in string. |
string match pattern str | Returns 1 if str matches the pattern, else 0. |
string range str i j | Returns the range of characters in str from i to j |
string tolower string | Returns string in lower case. |
string toupper string | Returns string in upper case. |
string trim string ?chars? | Trims the characters in chars from both ends of string. chars defaults to white space. |
string trimleft string ?chars? | Trims the characters in chars from the beginning of string. chars defaults to white space. |
string trimright string ?chars? | Trims the characters in chars from the end of string. chars defaults to white space. |
string wordend str ix | Returns the index in str of the character after the word containing the character at index ix. |
string wordstart str ix | Returns the index in str of the first character in the word containing the character at index ix. |
The append command
set foo z => z append foo a b c => zabc
The regexp command
regexp ?flags? pattern string ?match sub1 sub2 ...?The return value is 1 if some part of the string matches the pattern. Otherwise, the return value will be 0. The pattern does not have to match the whole string. If you need more control than this, you can anchor the pattern to the beginning of the string by starting the pattern with ^, or to the end of the string by ending the pattern with dollar sign, $. You can force the pattern to match the whole string by using both characters. For example:
set text1 "This is the first string" => This is the first string regexp "first string" $text1 => 1 regexp "second string" $text1 => 0
Jacl data structures
The basic data structure in the Jacl language is a string. There are two higher level data structures: lists and arrays. Lists are implemented as strings and the structure is defined by the syntax of the string. The syntax rules are the same as for commands. Commands are a particular instance of lists. Arrays are variables that have an index. The index is a string value so you can think of arrays as maps from one string (the index) to another string (the value of the array element).
Jacl lists
The lists of the Jacl language are strings with a special interpretation. In the Jacl language, a list has the same structure as a command. A list is a string with list elements separated by white space. You can use braces or quotes to group together words with white space into a single list element.
Command | Description |
list arg1 arg2 | Creates a list out of all its arguments. |
lindex list i | Returns the i'th element from list. |
llength list | Returns the number of elements in list. |
lrange list i j | Returns the i'th through j'th elements from list. |
lappend listVar arg arg ... | Appends elements to the value of listVar |
linsert list index arg arg ... | Inserts elements into list before the element at position index. Returns a new list. |
lreplace list i j arg arg ... | Replaces elements i through j of list with the args. Return a new list. |
lsearch mode list value | Returns the index of the element in list that matches the value according to the mode, which is -exact, -glob, or -regexp, -glob is the default. Return -1 if not found. |
lsort switches list | Sorts elements of the list according to the switches: -ascii, -integer, -real, -increasing, -decreasing, -command command. Return a new list. |
concat arg arg arg ... | Joins multiple lists together into one list. |
join list joinString | Merges the elements of a list together by separating them with joinString. |
split string splitChars | Splits a string up into list elements, using the characters in splitChars as boundaries between list elements. |
Arrays
set arr(index) valueSubstitute the dollar sign ($) to obtain the value of an array element, for example:
set foo $arr(index)For example:
set fruit(best) kiwi => kiwi set fruit(worst) peach => peach set fruit(ok) banana => banana array get fruit => ok banana worst peach best kiwi array exists fruit => 1The following table includes array commands:
Command | Description |
array exists arr | Returns 1 if arr is an array variable. |
array get arr | Returns a list that alternates between an index and the corresponding array value. |
array names arr ?pattern? | Return the list of all indices defined for arr, or those that match the string match pattern. |
array set arr list | Initializes the array arr from list, which should have the same form as the list returned by get. |
array size arr | Returns the number of indices defined for arr. |
array startsearch arr | Returns a search token for a search through arr. |
array nextelement arr id | Returns the value of the next element in array in the search identified by the token id. Returns an empty string if no more elements remain in the search. |
array anymore arr id | Returns 1 if more elements remain in the search. |
array donesearch arr id | Ends the search identified by id. |
Control flow commands
If Then Else
if boolean then body1 else body2The then and else keywords are optional. For example:
if {$x == 0} { puts stderr "Divide by zero!" } else { set slope [expr $y/$x] }
Switch
switch flags value pat1 body1 pat2 body2 ...You can also group all the pattern-body pairs into one argument:
switch flags value {pat1 body1 pat2 body2 ...}There are four possible flags that determines how value is matched.
switch -exact -- $value { foo {doFoo; incr count(foo)} bar {doBar; return $count(foo)} default {incr count(other)} }If the pattern that is associated with the last body is default, then the command body is started if no other patterns match. The default keyword only works on the last pattern-body pair. If you use the default pattern on an earlier body, it will be treated as a pattern to match the literal string default.
Foreach
foreach loopVar valueList commandBodyThe first argument is the name of a variable. The command body runs one time for each element in the loop with the loop variable having successive values in the list. For example:
set numbers {1 3 5 7 11 13} foreach num $numbers { puts $num }The result from the previous example will be the following output, assuming that only one server exists in the environment. If there is more than one server, the information for all servers returns:
1 3 5 7 11 13
While
while booleanExpr bodyThe while command repeatedly tests the boolean expression and runs the body if the expression is true (non-zero). For example:
set i 0 while {$i < 5} { puts "i is $i" incr i}The result from the previous example will be like the following output, assuming that there is only one server. If there is more then one servers, it will print all of the servers:
i is 0 i is 1 i is 2 i is 3 i is 4
For
for initial test final bodyThe first argument is a command to initialize the loop. The second argument is a boolean expression which determines if the loop body will run. The third argument is a command that runs after the loop body: For example:
set numbers {1 3 5 7 11 13} for {set i 0} {$i < [llength $numbers]} {incr i 1} { puts "i is $i" }The result from previous example will be like the following output, assuming that there is only one server in the environment. If there is more then one server, it will print all of the server names:
i is 1 i is 3 i is 5 i is 7 i is 11 i is 13
Break and continue
You can control loop execution with the break and continue commands. The break command causes an immediate exit from a loop. The continue command causes the loop to continue with the next iteration.
Catch
catch command ?resultVar?The first argument is a command body. The second argument is the name of a variable that will contain the result of the command or an error message if the command raises an error. The catch command returns a value of zero if no error was caught or a value of one if the command catches an error. For example:
catch {expr 20 / 5} result ==> 0 puts $result ==> 4 catch {expr text / 5} result ==> 1 puts $result ==> syntax error in expression "text / 5"
Return
Use the return command to return a value before the end of the procedure body or if a contrast value needs to be returned.
Namespaces
Jacl keeps track of named entities such as variables, in namespaces. The wsadmin tool also adds entries to the global namespace for the scripting objects, such as, the AdminApp object
When you run a proc command, a local namespace is created and initialized with the names and the values of the parameters in the proc command. Variables are held in the local namespace while you run the proc command. When you stop the proc command, the local namespace is erased. The local namespace of the proc command implements the semantics of the automatic variables in languages such as C and Java.
While variables in the global namespace are visible to the top level code, they are not visible by default from within a proc command. To make them visible, declare the variables globally using the global command. For the variable names that you provide, the global command creates entries in the local namespace that point to the global namespace entries that actually define the variables.
proc { ... } { global AdminConfig ... [$AdminConfig ...] }
Calling scripts using another script
Use the source command to call a Jacl script from another Jacl script. For example:
Create a script called test1.jacl.
source c:/temp/script/testProcedure.jacl printName Cathy Smith
source /temp/script/testProcedure.jacl printName Cathy Smith
proc printName {first last} { puts "My name is $first $last" }
Pass the following path as a script argument.
wsadmin -lang jacl -f c:/temp/script/test1.jacl
wsadmin -lang jacl -f '/temp/script/test1.jacl'
You must use forward slashes (/) as your path separator. Backward slashes (\) will not work.
Redirection using the exec command
eval exec ls -l > /tmp/outThe exec command of the Jacl scripting language does not fully support redirection therefore it might cause problems on some platforms.
open /tmp/out w puts $fileId $result close $fileIdIn some cases, you can also perform a redirection using shell and a .sh command redirection, not a redirection issued by Tcl.
For more information about Jacl, see the Scripting: Resources for Learning article.