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为*则调到末尾