04 Tcl字符串
Tcl字符串
4.1
Tcl将说有的变量值视作字符串,并将他们作为字符串进行保存。
命令 | 描述 |
---|---|
append | 将值追加到字符串尾 |
binary | 二进制化字符串 |
format | 字符串格式化 |
regexp | 正则表达式(用于字符串模式匹配) |
regsub | 用正则表达式进行字符串模式匹配和替换 |
scan | 字符串分解 |
string options | 字符串操作和命令集 |
subst | 字符替代(替代特殊字符) |
4.2 append
将一段字符串连接到另外一字符串形成新的字符串,此命令对变量直接进行修改。
append varName?value?
set var1 Hello
set var2 World
append var1 $var2
=>HelloWorld
puts $var1
=>HelloWorld # var1的内容被更改
4.3 format命令
4.3.1 format命令说明
format命令和C语言中的printf和sprintf命令类似,根据一组格式说明来格式化字符串。此命令不会更改被操作字符串的原有内容
# 使用格式
format spec value1 value2.....
- 例子
set res [format "%2\$s" 1 5 9]
- 上面的format语句要取第二个变元值。
- value1 value2 value3...就相当于一个列表的值--变元
- %--表示格式说明
- 2$--表示取第二个变元--变元的顺序从1开始数
- s--表示字符串
spec
spec包含了格式说明关键词和附加文字,使用%引入一个关键词,后跟0个或者多个修饰符,然后使用一个转换格式符结尾。("%关键词+附加文字+修饰符+格式转换符")
格式转换符
字符 | 说明 |
---|---|
d | 有符号整数 |
U | 无符号整数 |
i | 有符号整数,变元可以是十六进制Ox或者八进制O |
o | 无符号八进制 |
x、X | 无符号十六进制 |
C | 将整数映射到ACSII码表示的字符 |
s | 字符串 |
f | 浮点数 |
e、E | 科学计数法表示的浮点数 |
g、G | 以%f或%e来表示的浮点数 |
格式标志符
标志 | 说明 |
---|---|
- | 使字段左对齐 |
+ | 使字段右对齐 |
space | 在数字前加一个空格,除非数字有带前导符号。 |
0 | 用0补充空白 |
# | 前导O表示八进制,前导Ox表示十六进制数,浮点数中总要带上小数点。不删除末尾的0 |
- 位置说明符i$表示从第i个变元取值而不是根据通常的位置对应关系对应的变元。位置计数从1开始。
4.3.2 format举例
set str [format "%3\$s %1\$s %2\$s" "are" "right" "You"]
=> You are right
format "%x" 20
=>14 # x表示无符号十六进制数
format "%8x" 20
=> 14 # 将20转变为8位十六进制数,右对齐
format "%08x" 20 # 将20转换为十六进制数,8位数据宽度,用0填补
=>00000014
format "%#08x" 20 # 将20进制转变为十六进制数,8位数据宽度,用0填补,添加前导Ox
=>0x000014
set c [format %c%e%c 40 30000 41]
=>(3.000000e+004) # C表示将整数映射为ASCII字符,40和41对应“(”,“)”
set num [scan Aa %C Var1]
=>1 # 将字符串Aa的第一个字符A转换为对应整数
# 并赋值给Var1变量,返回成功转换的个数
puts $Var1
=>65 # 字符A对应的整数
- format格式命令中,“%C”一个整数转换为对应ASCII字符输出,如果一个字符转换为对应的整数,就需要scan命令来完成。
4.4 scan命令
scan命令根据格式描述解析一个字符串,并将对应的值赋值给后面的变量,成功后返回成功转换的个数。
scan string format var1?var?var?var?......
scan的格式描述几乎与format相同,但不用%U。%C的作用与format中的相反,是将一个ASCII字符转换为对应的整数值。
- format是将多个目标转换成一个字符串。
- scan是将一个字符串分解为多个变量。
- scan格式包含有一个集合的概念。它使用方括弧来界定一组字符,这个集合匹配拷贝字符串的一个或多个字符到目的变量中去。这种集合的概念在以后的regexp正则表达式中应用更多。
- 如果scan命令中,没有制定输出变量,则它不返回成功的个数,而返回成功转化的结果。
set num [scan "abcABC" "%C%C" var1 var2]
=>2
puts "$var1 $var2"
=>97 98
set num [scan "abcABC" "%C%C"]
=>97 98
puts $num
=>97 98 # 没有制定输出变量的结果
# 格式描述说明要扫描小写a-z区间的连续字符,用到了花括号表明是一个集合。
scan "abcABC" {%[a-z]} res
=>1
puts $res
=>abc # {} 表示一个字符串 %[a-z] 相当于正则表达式
# {%正则表达式}
scan "ABCabc" {%[A-b]} res
=>1
puts $res
=>ABCab
scan "ABCabc" {%[^a-b]} res # ^是表示非的意思,%2[^a-b] 2个不是a-b
=>1
puts $res
=>ABC
scan "ABCabc" {%2[^a-b]} res
=>1
puts $res
=>AB
4.5 binary命令
Tcl8.0之后支持二进制字符串。
根据数据的存储形式可以分为ASCII形式和二进制形式。
- 按ASCII形式存放的时候,每个字节存放一个ASCII代码,表示一个数字字符。
- 以二进制形式存放,将存储数字的二进制值,比如一个整数10000,用ASCII码表示时,每个数字用一个字节的ASCII码存储,共需要5个字节存储空间。使用二进制存储(将十进制的10000转变为二进制数0010,0111,0001,0000),只需要使用两个字节(一个字节8位)。
- 使用二进制存储要比使用ASCII码存储节省空间。在内存中,都是使用二进制进行存储的。
- binary format就是将数值根据规定的模式对tcl的普通数据进行二进制压缩,而binary scan作用相反,是从二进制数值恢复Tcl普通数据。
# 使用binary format对数值字符串25664进行二进制压缩,使用binary scan进行恢复
# 25664二进制数0110010001000000,需要使用两个字节进行存储
set b [binary format "s" 25664]
=>@d
puts $b
=>@d
binary scan $b "s" var
=>1
puts $var
=>25664
binary scan 1 C var
=>1
puts $var
=>49
- 整数25664以十六进制表示6440H。“s”为格式说明符,按照由低到高字节顺序存储。
- 数值被压缩为两个字节,输出结果为两个压缩字节对应的两个字符。
- @对应的ASCII码为40H,d的ASCII码为64H
- 从数字1恢复数值,字符1的ASCII码=31H,31H对应十进制整数为49。
语法
binary format spec value1?value...?
binary scan spec var1?var2.......?
spec为格式描述字符串
根式描述模板包括类型关键字和数值(type count)两个部分。下表总结了这些类型。表中,类型为跟在类型关键字字母后的可选计数。
类型 | 说明 |
---|---|
a | 包含count个字符的字符串,在binary format中以空白字符作为补白 |
A | 和a功能相同,使用空格符而不是空字符作为补白 |
b | 长度为count的二进制字符串,以0和1组成,按照从低到高的bit位顺序排列 |
B | 长度为count的二进制字符串,以0和1组成,按照从高到低的bit位顺序排列 |
h | 长度为count的十六进制字符串,按照从低到高的bit位顺序排列 |
H | 长度为count的十六进制字符串,按照从低到高的bit位顺序排列 |
C | 一个8位字符编码。binary scan中会从字符串中将字符转换为对应整数 |
s | 字节顺序为little-endian的16位整数。count用于指定重复特性 |
S | 字节顺序为big-endian的16位整数。count用于指定重复特性 |
i | 字节顺序为little-endian的32位整数。count用于指定重复特性 |
I | 字节顺序为big-endian的32位整数。count用于指定重复特性 |
f | 本机格式的单精度浮点数,count用于指定重复特性 |
d | 本机格式的双精度浮点数,count用于指定重复特性 |
x | 使用bianry format放置count个空字节 |
X | 回退count个字节 |
@ | 调到由count指定的绝对位置,如果count为*则调到末尾 |
几个小例子:
binary scan "abc" "c" var1
=>1
puts $var1
=>97
binary scan "abcd" "c3" val
=>1
puts $val
=>97 98 99
binary scan "abcd" "ccc" vala valb valc
=>3
puts "$vala $valb $valc"
=>97 98 99
# 将一个8位二进制数(0,1)转换成对应的字符串
binary format B8 01001001
注意:用binary format压缩的字符串,需要在同一系统上用binary scan来恢复。不同系统上的binary字符串可能处理的方式有所不同。
4.6 subst命令
subst命令在字符串中搜索方口号、$和反斜杠,并对其进行替换操作,而对其他数据不做处理。字符串内的花括号对这种替换操作不阻止。
subst {a=$a sum=[expr 1+2]}
=> a=foo bar sum=3
subst {a={$a} sum={[expr 1+2]}}
=>a={foo bar} sum={3} # 数据内部的{}不阻止替换