`
universsky
  • 浏览: 92885 次
文章分类
社区版块
存档分类
最新评论

脚本语言TCL教程:3

 
阅读更多

1. 字符串函数

序号

函数

解释

1

string tolower string1

string1转换为小写字母

2

string toupper string1

string1转换为大写字母

3

string trim string1 ? trimchars ?

去掉string1前后的trimchars字符,如果不指定,缺省为空格,trimlefttrimright一样的情况

4

string trimleft string1? trimchars ?

去掉string1左边的trimchars字符

5

string trimright string1? trimchars ?

去掉string1右边的trimchars字符

2. format 函数

格式:format formatstring ?arg1 arg2 ... argn ?

注意是format,不是string format

格式串列表:

序号

格式

描述

1

s

字符串

2

d

十进制整数

3

x

十六进制数值

4

o

八进制数值

5

f

浮点数

6

-

左对齐

7

+

右对齐,不指定 + ,缺省是右对齐

例子:020_stringmodify.tcl

set upper "THIS IS A STRING IN UPPER CASE LETTERS"

set lower "this is a string in lower case letters"

set trailer "This string has trailing dots ...."

set leader "....This string has leading dots"

set both "((this string is nested in parens )))"

puts "tolower converts this: $upper"

puts " to this: [string tolower $upper]\n"

puts "toupper converts this: $lower"

puts " to this: [string toupper $lower]\n"

puts "trimright converts this: $trailer"

puts " to this: [string trimright $trailer .]\n"

puts "trimleft converts this: $leader"

puts " to this: [string trimleft $leader .]\n"

puts "trim converts this: $both"

puts " to this: [string trim $both "()"]\n"

set a " trim "

puts "[string trim $a]" ;#返回trim,说明缺省是去掉的空格

set labels [format "%-20s %+10s " "Item" "Cost"] ;# %-20s:总长度20,字符串左对齐

set price1 [format "%-20s %10d Cents Each" "Tomatoes" "30"] ;# %10d:总长度10,数值右对齐

set price2 [format "%-20s %10d Cents Each" "Peppers" "20"]

set price3 [format "%-20s %10d Cents Each" "Onions" "10"]

set price4 [format "%-20s %10.2f per Lb." "Steak" "3.59997"] ;#%10.2f:总长度10,小数点后两位,数值右对齐

puts "\n Example of format:\n"

puts "$labels"

puts "$price1"

puts "$price2"

puts "$price3"

puts "$price4"

1.10:正则表达式

1. 利用正则表达式在字符串中查找子串

格式:regexp ?switches?exp string1?matchVar? ?subMatch1 ... subMatchN?

例如:regexp {([A-Za-z]+) +([a-z]+)} $sample match sub1 sub2

Ø switches exp :正则表达式,使用 {} 包含,如果使用””包含,需要转义符才能执行

Ø $sample :被查找的字符串

Ø match:满足{([A-Za-z]+) +([a-z]+)}匹配的子串传递给match

Ø sub1:满足([A-Za-z]+)的子串传递给sub1,正则表达式中圆括号的匹配项会将结果按顺序传递给后面的变量

Ø sub2:满足([a-z]+)的子串传递给sub2,正则表达式中圆括号的匹配项会将结果按顺序传递给后面的变量

2. 利用正则表达式在字符串中替换子串

格式:regsub ?switches? exp string1 subSpec VarName

例如:regsub "way" $sample "lawsuit" sample2

switches exp:正则表达式,此处是字符串"way"

string1:被替换的字符串

subSpec:替换为什么字符串,此处是"lawsuit"

VarName:替换后的结构赋给的变量

注意:只替换一次。

3. 正则表达式常用通配符列表

序号

通配符

描述

1

^

匹配一个字符串的开头

2

$

匹配一个字符串的结尾

3

.

匹配任意一个字符

4

*

匹配0n个任意字符

5

+

匹配1n个任意字符

6

[...]

匹配一个字符集合,例如:[a-z]代表匹配所有小写字母

7

[^...]

匹配不包括该集合,例如:[^a-z]代表匹配所有非小写字母

8

(...)

圆括号会将其中的正则表达式的匹配项传递给后面的变量

例子:021_regular.tcl

set sample "Where there is a will, There is a way."

set result [regexp {[a-z]+} $sample match]

puts "Result: $result match: $match" ;#返回here

set result [regexp {([A-Za-z]+) +([a-z]+)} $sample match sub1 sub2 ]

puts "Result: $result Match: $match 1: $sub1 2: $sub2" ;#sub1=Where, sub2=there

set result [regexp {([A-Za-z]+)( +)([a-z]+)} $sample match sub1 sub2 sub3]

puts "Result: $result Match: $match 1: $sub1 2: $sub2 3: $sub3" ;#返回的结果为:sub1=Where,sub2是一个空格,sub3=there。说明加上圆括号就能将匹配子串传递给后面的变量

regsub "way" $sample "lawsuit" sample2

puts "New: $sample2"

set sample "Where there is a will, There is a way way."

regsub "way" $sample "lawsuit" sample2

puts "New: $sample2" ;#返回结果: ..There is a lawsuit way. 可以看出只是替换了左边的一个way

1.11:更多正则表达式

正则表达式非常重要,虽然已经有正则表达式的工业标准,但是实际情况并不完全统一,perlshelltcljava等的正则表达式都有些许区别,所以大家需要留心细节。

1[^ ]* 0n个非零字符

2 * 0n个零

3[0-9]+ 1n个数字

4[^/]* 0n个非反斜杠字符

5(/[a-z]*) :前面是一个反斜杠,后面跟着0n个小写字母

6([^\t]+) :非制表符的任意字符

7(\t) :一个制表符

8\\\[ :其实是匹配的\[ ,因为书写的时候需要转义符

例子:

set list1 [list {/dev/wd0a 17086 10958 5272 68% /}\

{/dev/wd0f 179824 127798 48428 73% /news}\

{/dev/wd0h 1249244 967818 218962 82% /usr}\

{/dev/wd0g 98190 32836 60444 35% /var}]

foreach line $list1 {

regexp {[^ ]* *([0-9]+)[^/]*(/[a-z]*)} $line match size mounted;

puts "$mounted is $size blocks"

# get every field value

regexp {^([^ ]*)} $line match first;

regexp {[^ ]* *([0-9]*)} $line match first;

regexp {[^ ]* *[0-9]* *([0-9]*)} $line match first;

regexp {[^ ]* *[0-9]* *[0-9]* *[0-9]* *([0-9]*%)} $line match first;

regexp {[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% *(/[a-z]*)} $line match first;

regexp {(/[a-z]*)$} $line match first;

puts "$first";

}

# get two number

regexp {.(.[0-9]*).a} "3343a" match ss;

puts "$ss"

set line {Interrupt Vector? [32(0x20)]}

regexp "\[^\t]+\t\\\[\[0-9]+\\(0x(\[0-9a-fA-F]+)\\)]" $line match hexval ;#看得人头晕,建议各位还是用花括号吧

puts "Hex Default is: 0x$hexval"

set str2 "abc^def"

regexp "\[^a-f]*def" $str2 match

regexp {[a-z]*\^[a-z]*$} $str2 match

puts "using \[^a-f] the match is: $match"

regexp "\[a-f^]*def" $str2 match

regexp {[a-f^]*def} $str2 match

puts "using \[a-f^] the match is: $match"

regsub {\^} $str2 " is followed by: " str3

puts "$str2 with the ^ substituted is: \"$str3\""

regsub "(\[a-f]+)\\^(\[a-f]+)" $str2 "\\2 follows \\1" str3

puts "$str2 is converted to \"$str3\""

注意:

1()[]的区别

(ab) 代表的是ab串,也就是说ab是有顺序的

[ab] 代表的是a,b等,代表的是不确定的数个字符,没有顺序问题

2

[^a-z] 代表的是非 a-z 的任意字符

[a-z^] 代表的是 a-z ^ 字符,此处的^ 不代表非的意思,它和a,b,c 一样是个单独的字符

3

[a-z]* ([a-z]*) 的区别:

例子:

regexp {([0-9]*)} "333" match ss;

puts "$ss" ;#有括号才有返回,没有括号就没有返回

1.1 数组

1.数组相关命令

序号

命令

描述

1

array exists arrayName

判断一个数组是否存在,数组存在返回1,数组不存在返回0

2

array names arrayName ?pattern

返回一个数组的指示列表,相当于数组的第一维,如果没有匹配串则完全返回

3

array size arrayName

返回数组的列数,相当于数组的第二维数目

4

array get arrayName

取得数组的值列表,它使数组的赋值变得简单,例如:

array set arrayX [array get arrayY] ,实现了将arrayY赋值给arrayX

5

array set arrayName datalist

数组定义

例子:023_array.tcl

array set array1 [list {123} {Abigail Aardvark} \

{234} {Bob Baboon} \

{345} {Cathy Coyote} \

{456} {Daniel Dog} ]

puts "Array1 has [array size array1] entries\n"

puts "Array1 has the following entries: \n [array names array1] \n"

puts "ID Number 123 belongs to $array1(123)\n"

set array1(123) {modified}

set array1(123) "modified"

puts "ID Number 123 belongs to $array1(123)\n"

array set array3 [array get array1] ;#可以看出tcl中的数组赋值非常简单,不用写循环来赋值

puts "Array3 has [array size array3] entries\n"

puts "Array3 has the following entries: \n [array names array3] \n"

puts "Array3 has the following entries while using pattern: \n [array names array3 *2*] \n" ;#使用匹配串

puts "ID Number 123 belongs to $array3(123)\n"

if {[array exist array1]} {

puts "array1 is an array"

} else {

puts "array1 is not an array"

}

if {[array exist array2]} {

puts "array2 is an array"

} else {

puts "array2 is not an array"

}

1.2 :更多数组相关

1. 使用foreach浏览数组内容;

2. 使用array startsearcharray anymore array nextelement 浏览数组内容;

3. 数组相关函数列表:

序号

函数

描述

1

array startsearch arrayName

得到数组第一项,返回的是id

2

array nextelement arrayName searchID

得到数组的下一项,返回的是id

3

array anymore arrayName searchID

根据当前的id判断是否还有内容,返回1为找到,返回0为没有找到

4

array donesearch arrayName searchID

根据id查找相应项,会破坏相应的状态信息

4. globalupvar的使用注意事项

global

upvar

普通变量

函数内

$

$

函数外

$

不用$

数组变量

函数内

$

$

函数外

不用$

不用$

解释:除了global普通变量函数内外都用$,其他都是函数外不用$,函数内用$。特例不考虑。

下面有详细的例子

例子:024_array.tcl

array set array1 [list {123} {Abigail Aardvark} \

{234} {Bob Baboon} \

{345} {Cathy Coyote} \

{456} {Daniel Dog} ]

;#

;# Simply iterating through an array with a foreach loop:

;#

foreach id [array names array1] { ;#浏览数组内容方法一

puts "$array1($id) has ID: $id"

}

;# Without sorted even turn is not original

;# Two procs iterating through the same array with iteration commands

;#

proc getrec_format1 {arrayVar searchid} {

global $arrayVar

upvar $searchid id ;#注意这里的id并非在上一层次中已经定义的一个变量,他只是表明通过参数修改的是上一级堆栈的变量,此处id随便改成一个上一级堆栈并未定义的变量名是没有问题的,可以试试将id改为id1

set record [array nextelement $arrayVar $id];

return "The current ID is: $record"

}

;# proc getrec_format1 {arrayVar searchid} { ;#这种写法是其他语言最常用的写法,但是tcl中是错误的,数组的传递与其他简单类型不同

;# set record [array nextelement $arrayVar $searchid];

;# return "The current ID is: $record"

;# }

proc getrec_format2 {arrayVar searchid} {

global $arrayVar

upvar $searchid id

set record [array nextelement $arrayVar $id];

return $record;

}

set searchId [array startsearch array1] ;# 123开始,浏览数组内容方法二

puts ""

set item 0;

while {[array anymore array1 $searchId]} {

incr item;

if {[expr $item %2]} {

set format1 [getrec_format1 array1 searchId]

puts "item number: $item format 1: $format1"

} else {

set format2 [getrec_format2 array1 searchId]

puts "item number: $item format 2: $format2"

}

}

;#普通类型global传值

proc tryglobal {glo} {

global $glo

return "The current glo is: $glo"

}

set glo1 "12341234"

puts "[tryglobal glo1]" ;#返回glo1, 而用upvar,就不加$ 在前面

puts "[tryglobal $glo1]" ;#返回 12341234

;#普通类型upvar传值

proc tryupvar {upv} {

upvar $upv upv1

return "The current upv is: $upv1"

}

set upv1 "1234512345"

puts "[tryupvar upv1]" ;#返回1234512345

;# puts "[tryupvar $upv1]" ;#出错了

;#定义一个数组后面用

array set arr1 [list {1} {2} {3} {4}] ;# 会被理解为二维的,13array names24是值

;#数组类型global传值

proc tryarrglobal {arrglo} {

global $arrglo

return "The current glo is: [array names $arrglo]"

}

;#puts "[tryarrglobal arr1]" ;#函数中arrglo:

;#puts "[tryarrglobal $arr1]" ;#函数中arrglo:出错了

puts "[ tryarrupvar arr1]" ;#函数中$arrglo:正确:返回13

;#puts "[ tryarrupvar $arr1]" ;#函数中$arrglo:出错了

;#数组类型upvar传值

proc tryarrupvar {arrglo} {

upvar $arrglo arrglo1

return "The current glo is: [array names $arrglo1]"

}

;#puts "[tryarrglobal arr1]" ;#函数中arrglo1: 正确:返回13

;#puts "[tryarrglobal $arr1]" ;#函数中arrglo1: arrglo出错了

puts "[ tryarrupvar arr1]" ;#函数中$arrglo1:正确:返回13,建议

;#puts "[ tryarrupvar $arr1]" ;#函数中$arrglo1:出错了

;# 参数传递非常容易混乱,所以举的例子,没有用文字说明,下面来总结一下

;# global: 普通变量:函数内:用$ 函数外:用$ 数组:函数内:用$ 函数外:不用$

;# upvar: 普通变量:函数内:用$ 函数外:不用$ 数组:函数内:用$ 函数外:不用$ 或函数内:不用$ 函数外:不用$

;# 一句话:除了global普通变量函数内外都用$,其他都是函数外不用$,函数内用$。特例不考虑。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics