博主注: 最近要写WAS的wsadmin脚本和JACL脚本,要参考文档,网上jacl的中文资料不多,找了下自己以前的收藏,居然有这么好的东东。现在拿出来分享下。简单介绍下:JACL(Java Command Language)是Tcl 脚本语言的 Java 实现。它是一个开源项目,用户遵循GNU LGP许可。它的在线英文文档地址是http://jacl.sourceforge.net/
http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/topic/com.ibm.websphere.express.doc/info/exp/ae/rxml_slinks.html 。可以去http://tcljava.sourceforge.net/docs/website/download.html下载jacl。
本文具体转载自哪里已经不得而知,望译者见谅!
Jacl
Jacl 是 TCL 的一个备用实现,它是完全使用 Java 代码编写的。
wsadmin 工具使用 Jacl V1.3.1。
基本语法:
Jacl 命令的基本语法如下:
Command arg1 arg2 arg3 ...
命令可以是一个内置命令名,也可以是一个 Jacl 过程。例如:
puts stdout {Hello, world!}
=> Hello, world!
在此示例中,命令是 puts ,它有两个参数、一个 I/O 流标识和一个字符串。 puts 命令将字符串与尾随的新行字符一起写入 I/O 流。参数由命令解释。在该示例中, stdout 用于标识标准输出流。将 stdout 用作名称是由 puts 命令和其他 I/O 命令使用的约定。 stderr 识别标准错误输出,而 stdin 识别标准输入。
变量
set 命令将值指定给变量。此命令有两个参数:变量的名称和值。变量名可以是任何长度,且区分大小写。使用 Jacl 变量前无须声明它们。解释器将在第一次指定值时创建变量。例如:
set a 5
=> 5
set b $a
=> 5
第二个示例将变量 a 的值指定给变量 b 。使用美元标记( $)表明变量替换。您可以使用 unset 命令删除变量,例如:
unset varName1 varName2 ...
您可以将任何数量的变量传递到 unset 命令。如果尚未定义变量, unset 命令将报错。您可以使用 unset 命令删除整个数组或只删除单个数组元素。在数组上使用 unset 命令是清除大数据结构的简便方式。可以用 info exists 命令测试变量是否存在。因为 incr 参数首先要求变量存在,所以可能必须测试变量是否存在,例如:
if ![info exists foobar] {set foobar 0} else {incr foobar}
命令替换:
替换的第二种格式是命令替换。嵌套命令由方括号( [ ] )分隔。 Jacl 解释器对方括号中的所有内容求值,并将其作为一条命令求值。例如:
set len [string length foobar]
=> 6
在此示例中,嵌套命令如下: string length foobar 。 string 命令对字符串执行各种操作。在这种情况下,命令要求字符串 foobar 的长度。单个命令中有几种命令替换情况,解释器从左括号至右括号处理它们。例如:
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
数学表达式:
Jacl 解释器不对数学表达式求值。使用 expr 命令对数学表达式求值。 expr 命令的实现采用所有参数,将它们并置到一个字符串中,并将该字符串作为数学表达式进行语法分析。 expr 命令计算答案后,它格式化到字符串中并返回。例如:
expr 7.2 / 3
=> 2.4
反斜杠替换:
Jacl 解释器执行的最后一个替换类型是反斜杠替换。使用它来引用对解释器有特殊含义的字符。例如,如果要指定美元标记、花括号或括号字符,您可以用反斜杠来对它 进行引用。如果您正在使用许多反斜杠,那么您可以代之以使用花括号将内容分组,以关闭特殊字符的所有解释。有几种必需反斜杠的情况。例如:
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 {$ {} [] { [ } ]}
=> $ {} [] { [ } ]
您还可以使用反斜杠将长命令在多个行上继续。没有反斜杠的新行将终止命令。作为一行中最后字符的反斜杠将转换为空格。例如:
set totalLength [expr [string length "first string"] + \
[string length "second string"]]
=> 25
用花括号和双引号分组:
使用双引号和花括号将字分组在一起。引号允许组中发生替换,而花括号阻止替换。此规则适用于命令、变量和反斜杠替换。例如:
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].
在第二个示例中, Jacl 解释器从 puts 命令在第二个参数上执行变量和命令替换。在第三个命令中阻止替换,因此字符串按原样打印。
因为 Jacl 语言使用反斜杠字符( \)作为转义字符,所以还必须特别注意路径描述。要修正此问题,可在分布式路径语句中用正斜杠来替换每个反斜杠,或使用两个反斜杠。例如: C:/ 或 C:\\
过程和作用域:
Jacl 使用 proc 命令定义过程。定义过程的基本语法如下:
proc name arglist body
第一个参数是正在定义的过程的名称。该名称是区分大小写的,实际上它可以包含任何字符。过程名称和变量名不会相互冲突。第二个参数是过程的参数列表。第三个参数是条命令,或更通常是形成过程主体的一组命令。一旦定义 Jacl 过程,它将与任何内置命令一样使用。例如:
proc divide {x y} {
set result [expr $x/$y]
puts $result
}
在脚本中,这是调用 devide 过程的方式:
divide 20 5
它会给出类似以下的结果:
4
在此示例中并非真正必须使用变量 c。该过程主体也可写为:
return [expr sqrt($a * $a + $b * $b)]
此示例中的 return 命令是可选的,因为 Jacl 解释器将主体中最后一条命令值作为过程值返回。因此,该过程主体可以减少为:
expr sqrt($a * $a + $b * $b)
该过程结果是主体中最后一条命令返回的结果。 return 命令可用于返回特定值。
过程名称中存在单个、全局作用域。您可以在另一个过程中定义过程,但是在任何位置都可以看到它。变量和过程有不同的名称空 间,因此您的过程和变量可以有同一名称而不会有冲突。每个过程都有变量的本地作用域。过程中引入的变量仅在过程调用期间存在。过程返回后,取消定义那些变 量。如果外部作用域中存在同一变量名,那么使用过程中的变量名不会对它产生影响。过程外部定义的变量对于过程不可视,除非使用了全局作用域命令。
- global 命令 - 全局作用域是顶级作用域。此作用域在任何过程外。必须通过使用 global 命令使变量在可以访问过程中命令的全局作用域中定义。 global 命令的语法如下:
global varName1 varName2 ...
注释
使用井号字符( #)进行注释。
命令行参数
Jacl shell 将命令行参数作为 argv 变量的值传递到脚本。命令行参数数由 argc 变量提供。程序或脚本的名称不是 argv 的一部分,也不会由 argc 计数。 argv 变量是个列表。使用 lindex 命令从参数列表抽取项,例如:
set first [lindex $argv 0]
set second [lindex $argv 1]
字符串和模式匹配
字符串是 Jacl 语言中的基本数据项。您有多条命令可用于处理字符串。 string 命令的一般语法如下:
string operation stringvalue otherargs
operation 参数确定字符串的操作。第二个参数是字符串值。根据操作,可能还有其他参数。
下表包含 string 命令的摘要:
命令 | 描述 |
string compare str1 str2 | 按字典顺序比较字符串。如果相等则返回 0,如果 str1 排在 str2 前则返回 -1,其他情况则返回 1。 |
string first str1 str2 | 返回 str1 第一次出现在 str2 中的索引,如果未找到 str1,那么返回 -1。 |
string index string index | 返回指定索引的字符。 |
string last str1 str2 | 返回 str1 最后一次出现在 str2 中的索引,如果未找到 str1,那么返回 -1。 |
string length string | 返回字符串中的字符数。 |
string match pattern str | 如果 str 匹配模式,那么返回 1,否则返回 0。 |
string range str i j | 返回从 i 到 j 的 str 的字符范围 |
string tolower string | 以小写字母返回字符串。 |
string toupper string | 以大写字母返回字符串。 |
string trim string ?chars? | 从字符串两端修剪 chars 中的字符。 chars 缺省为空格。 |
string trimleft string ?chars? | 从字符串开头修剪 chars 中的字符。 chars 缺省为空格。 |
string trimright string ?chars? | 从字符串末尾修剪 chars 中的字符。 chars 缺省为空格。 |
string wordend str ix | 返回字符的 str 中的索引,该字符在包含索引 ix 的字符的字后。 |
string wordstart str ix | 返回第一个字符的 str 中的索引,该字符在包含索引 ix 的字符的字中。 |
append 命令
append 命令的第一个参数是变量名。它将剩余的参数并置到命名变量的当前值。例如:
set foo z
=> z
append foo a b c
=> zabc
regexp 命令
regexp 命令提供对正则表达式匹配器的直接访问。语法如下:
regexp ?flags? pattern string ?match sub1 sub2 ...?
如果字符串的一部分与模式匹配,那么返回值是 1 。否则,返回值将为 0 。模式不必匹配整个字符串。如果您需要更多控制,那么可以将 ^ 放在模式开头,从而将模式固定到字符串开头,或者可以将美元标记 $ 放在模式末尾,从而将模式固定在字符串末尾。您可以通过使用这两个字符强制模式匹配整个字符串。例如:
set text1 "This is the first string"
=> This is the first string
regexp "first string" $text1
=> 1
regexp "second string" $text1
=> 0
Jacl 数据结构
Jacl 语言中的基本数据结构是字符串。其中存在两种更高级别的数据结构:列表和数组。列表作为字符串来实现,而结构由字符串的语法定义。语法规则与命令相同。命 令是列表的特殊实例。数组是有索引的变量。索引是字符串值,因此您可以将数组看作是从一个字符串(索引)到另一个字符串(数组元素值)的映射。
Jacl 列表
Jacl 语言的列表是有特殊解释的字符串。在 Jacl 语言中,列表与命令有同一结构。列表是字符串,具有以空格分隔的列表元素。您可以使用花括号或引号将具有空格的字一起分组到一个列表元素中。
下表包含有关列表的命令:
命令 | 描述 |
list arg1 arg2 | 用列表的所有参数来创建它。 |
lindex list i | 返回列表的第 i 个元素。 |
llength list | 返回列表中的元素数。 |
lrange list i j | 返回列表的第 i 到第 j 个元素。 |
lappend listVar arg arg ... | 将元素追加到 listVar 的值 |
linsert list index arg arg ... | 将元素插入到列表中位置索引的元素前。返回一个新的列表。 |
lreplace list i j arg arg ... | 用 args 替换列表中的元素 i 到 j。返回一个新的列表。 |
lsearch mode list value | 返回根据方式匹配值的列表中元素的索引,分别是 -exact、 -glob 或 -regexp, -glob 是缺省值。如果未找到,那么返回 -1。 |
lsort switches list | 根据以下开关符对列表的元素进行排序: -ascii、 -integer、 -real、 -increasing、 -decreasing、 -command 命令。返回一个新的列表。 |
concat arg arg arg ... | 将多个列表连接起来,成为一个列表。 |
join list joinString | 通过用 joinString 分隔列表中的元素,从而将它们合并起来。 |
split string splitChars | 将字符串完全分割为列表元素,使用 splitChars 中的字符作为列表元素间的边界。 |
数组
数组是 Jacl 语言中的另一主要数据结构。数组是具有已赋值的字符串索引的变量,因此您可以将数组看作是从字符串到字符串的映射。数组在内部用散列表实现。访问每个元素 的成本几乎相同。数组的索引由圆括号定界。索引可以有任何字符串值,而且它可以是变量或命令替换的结果。数组元素用 set 命令定义,例如:
set arr(index) value
替换美元标记( $)以包含数组元素的值,例如:
set foo $arr(index)
例如:
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
=> 1
下表包含数组命令:
命令 | 描述 |
array exists arr | 如果 arr 是数组变量,那么返回 1。 |
array get arr | 返回以索引和相应的数组值交替出现的列表。 |
array names arr ?pattern? | 返回为 arr 定义的所有索引或匹配字符串匹配模式的索引列表。 |
array set arr list | 初始化列表的数组 arr,该列表应该与 get 返回的列表具有相同格式。 |
array size arr | 返回为 arr 定义的索引数。 |
array startsearch arr | 返回搜索整个 arr 的搜索令牌。 |
array nextelement arr id | 在由令牌标识识别的搜索中,返回数组中下一个元素的值。如果搜索中不再有元素,那么返回空字符串。 |
array anymore arr id | 如果搜索中还有元素,那么返回 1。 |
array donesearch arr id | 结束由 id 识别的搜索。 |
控制流命令
存在以下循环命令:
- while
- foreach
- for
以下是条件命令:
- if
- switch
以下是错误处理命令:
- catch
以下命令微调控制流:
- break
- continue
- return
- error
If Then Else
if 命令是基本条件命令。它说明:如果表达式为真,那么返回第二个代码行,否则运行另一代码行。第二个命令主体( else 子句)是可选的。命令语法如下:
if boolean then body1 else body2
then 和 else 关键字是可选的。例如:
if {$x == 0} {
puts stderr "Divide by zero!"
} else {
set slope [expr $y/$x]
}
Switch
根据表达式的值,使用 switch 命令分支到多条命令中的某条命令。您可以基于模式匹配和简单比较来进行选择。可以指定任何数量的模式 -主体对。如果多个模式匹配,那么只对第一个匹配模式的代码主体求值。该命令的一般格式如下:
switch flags value pat1 body1 pat2 body2 ...
您还可以将所有模式 -主体对分组到一个参数中:
switch flags value {pat1 body1 pat2 body2 ...}
有四个可能的标志确定值如何匹配。
- -exact 将值与某个模式完全匹配。
- -glob 使用通配符样式模式匹配。
- -regexp 使用正则表达式模式匹配。
- -- 没有标志(或标志结束)。当值可以用虚线( - )开头时有用。
例如:
switch -exact -- $value {
foo {doFoo; incr count(foo)}
bar {doBar; return $count(foo)}
default {incr count(other)}
}
如果与上一个主体关联的模式是 default ,那么没有其他模式匹配时启动该命令主体。 default 关键字仅对上一个模式 /主体对起作用。如果对更前面的主体使用缺省模式,那么会将它作为模式对待以匹配文字串缺省值。
Foreach
foreach 命令循环整个命令主体,并将循环变量指定给列表中的每个值。语法如下:
foreach loopVar valueList commandBody
第一个参数是变量名。命令主体对循环中的每个元素运行一次,且循环变量有列表中的连续值。例如:
set numbers {1 3 5 7 11 13}
foreach num $numbers {
puts $num
}
假定环境中只存在一台服务器,上一个示例的结果将为以下输出。如果存在多台服务器,那么返回所有服务器的信息:
13 5711
13
While
while 命令采用两个参数;测试和命令主体,例如:
while booleanExpr body
如果表达式为 true(非零),那么 while 命令重复测试布尔表达式并运行主体。例如:
set i 0
while {$i < 5} {
puts "i is $i"
incr i}
假定只有一台服务器,上一个示例的结果将类似以下输出。如果存在多台服务器,那么将打印所有服务器:
i is 0
i is 1
i is 2
i is 3
i is 4
For
for 命令类似于 C 语言的 for 语句。它采用四个参数,例如:
for initial test final body
第一个参数是初始化循环的命令。第二个参数是确定循环主体是否将运行的布尔表达式。第三个参数是在循环主体后运行的命令,例如:
set numbers {1 3 5 7 11 13}
for {set i 0} {$i < [llength $numbers]} {incr i 1} {
puts "i is $i"
}
假定环境中只有一台服务器,上一个示例的结果将类似以下输出。如果存在多台服务器,那么它将打印所有服务器名:
i is 1
i is 3
i is 5
i is 7
i is 11
i is 13
break 和 continue
您可以使用 break 和 continue 命令控制循环执行。 break 命令会导致立即从循环中退出。 continue 命令会导致循环继续执行下一个迭代。
Catch
如果用错误的参数数调用命令,或者如果命令检测到特定于其实现的某些出错条件,将产生错误。未获取的错误会阻止脚本运行。使用 catch 命令获取这种错误。 catch 命令采用两个参数,例如:
catch command ?resultVar?
第一个参数是命令主体。第二个参数是变量名,它将包含命令结果或错误消息(如果命令产生错误)。如果没有获取错误,那么 catch 命令返回值 0,如果该命令获取了错误,那么返回值 1。例如:
catch {expr 20 / 5} result
==> 0
puts $result
==> 4
catch {expr text / 5} result
==> 1
puts $result
==> syntax error in expression "text / 5"
Return
在过程主体结束前之前或在需要返回对比值时,请使用 return 命令来返回值。
Namespaces
Jacl 将一些命名实体(例如,变量)保存在名称空间中。 wsadmin 工具还将条目添加到脚本编制对象(例如, AdminApp 对象)的全局名称空间。
运行 proc 命令时,用 proc 命令中的参数名称和参数值创建和初始化了本地名称空间。运行 proc 命令时,变量保存在本地名称空间中。停止 proc 命令时,将擦除本地名称空间。 proc 命令的本地名称空间实现语言(例如, C 和 Java)中自动变量的语义。
当全局名称空间中的变量对于顶层代码可视时,缺省情况下它们从 proc 命令内不可视。要使它们可视,请使用 global 命令全局声明这些变量。对于您提供的变量名,全局命令在本地名称空间中创建条目,它们指向实际定义这些变量的全局名称空间条目。
如果在 proc 中使用 wsadmin 工具提供的脚本编制对象,那么必须在可以使用它前先全局声明,例如:
proc { ... } {
global AdminConfig
... [$AdminConfig ...]
}
使用一个脚本调用其他脚本
请使用 source 命令来从一个 Jacl 脚本调用另一个 Jacl 脚本。例如:
创建称为 test1.jacl 的脚本。
source c:/temp/script/testProcedure.jacl
printName Cathy Smith
创建称为 testProcedure.jacl 的脚本。
proc printName {first last} {
puts "My name is $first $last"
}
请将以下路径作为脚本参数进行传递。
wsadmin -lang jacl -f c:/temp/script/test1.jacl
必须将正斜杠( /)用作路径分隔符。反斜杠( \)将不起作用。
使用 exec 命令重定向
以下用于重定向的 Jacl exec 命令在 Linux 平台上不起作用:
eval exec ls -l > /tmp/out
Jacl 脚本编制语言的 exec 命令不完全支持重定向,因此该命令在某些平台上可能会产生问题。
使用 Jacl 语言的 exec 命令时,不要使用重定向。相反,可以将用于重定向的 exec 命令保存在一个变量中,然后将该变量写入文件,例如:
open /tmp/out w puts $fileId $result close $fileId
在某些情况下,还可以使用 shell 和 .sh 命令重定向(而不是 Tcl 发出的重定向)来执行重定向。
要获取更多有关 Jacl 的信息,请参阅 脚本编制:学习资源 一文。