字符串
1. 基本命令集
Tcl 将所有的变量值视作字符串,并将他们作为字符串来保存。下表列出了字符串操作的几个常用命令。
命令 | 描述 |
append | 将值追加到字符串尾 |
binary | 二进制字符串操作 |
format | 字符串格式化 |
regexp | 正则表达式(用于字符串模式匹配) |
regsub | 用正则表达式进行字符串模式匹配和替换 |
scan | 字符串分解 |
string options | 字符串操作和命令集 |
subst | 字符替代(替代特殊字符) |
2. append 命令
append 命令比较简单,它将一段字符串连接到另一字符串尾部从而组成新的字符串。此命令对变量直接修改。
语法:
- append varName ?value?
示例:
-
set var1 Hello
-
set var2 world
-
append var1 $var2
-
=> helloWorld
-
-
puts $var1
-
=> helloWorld #var1的内容被更改
-
3. format命令
format 命令和 C 语言中的 printf 和 sprintf 命令类似。它根据一组格式说明来格式化字符串。此命令不会改变被操作字符串的内容。
语法:
- format spec value1 value2 ...
spec:spec 变元包含了格式说明关键词和附加文字。使用%来引入一个关键词,后跟 0 个或者多个修饰符,然后使用一个转换格式符结尾。
关键词的基本格式是“ %aaaB”: aaa 是修饰符, B 代表一种格式转换符。例如%f 用于将对应位置的参数转化为浮点数。 如果要使用”%”号,则可以使用%%来实现。否则会将%后的字符作为关键词来处理。
valueX:valueX 是变元。对每个变元来讲,其关键词可多达 6 部分:
- 位置说明符;
- 标志;
- 字段宽度;
- 精度;
- 长度;
- 转换符。
转换符之外的关键词都可以看作修饰符。
格式转换符:
字符 | 说明 |
d | 有符号整数 |
u | 无符号整数 |
i | 有符号整数。变元可以是十六进制( 0x)或八进制(0)格式 |
o | 无符号八进制数 |
x 或 X | 无符号十六进制数 |
c | 将整数映射到对应的 ASCII 字符 |
s | 字符串 |
f | 浮点数 |
e 或 E | 科学记数法表示的浮点数 |
g 或 G | 以%f 或%e 格式(要短一些)来表示的浮点数 |
格式标志符:
标志 | 说明 |
- | 使字段左对齐 |
+ | 字段右对齐 |
space | 在数字前加一个空格,除非数字带有前导符号。这在将许多数字排列在一起时非常有用 |
0 | 使用 0 作为补白 |
# | 前导 0 表示八进制,前导 0x 表示十六进制数。浮点数中总要带上小数点。不删除末尾的 0(%g) |
位置说明符:i$表示从第 i 个变元取数值而不是根据通常的位置对应关系对应的变元。位置记数从 1 开始。
位置说明符示例:
-
set res [format "%2$s" 1 5 9] #\用来引用符号
,即取第二个元素5-
=> 5
-
-
puts $res
-
=> 5
-
-
set str [format "%3$s %1$s %2$s" "are" "right" "You"]
-
=> You are right
-
其它示例:
-
format "%x" 20 #将20转换为16进制数
-
=> 14
-
-
format "%8x" 20 #将20转换为16进制数,8位数据宽度,右对齐
-
=> 14
-
-
format "%08x" 20 #将20转换为16进制数,8位数据宽度,用0添齐
-
=> 00000014
-
-
format "%-8x" 20 #将20转换为16进制数,8位数据宽度,左对齐
-
=> 14
-
-
format "%#08x" 20 #将20转换为16进制数,并添加前缀0x,总宽度为8,右对齐(默认),前导空格用0补齐
-
=> 0x000014
-
4. scan命令
scan 命令根据格式描述符来解析一个字符串并将对应值赋给后面的变量。返回成功转换的个数。
语法:
- scan string format var? var? ....
scan 的格式描述几乎与 format 相同,但不用%u 格式。 %c 的作用与 format 中的相反,是将一个 ASCII 字符转换为对应的整数值。
应该注意 scan 命令中位置顺序和 format 中的不一样。 format 将多个目标变量转换成一个字符串,而 scan 则可将一个字符串分解为多个变量。
如果 scan 命令中,没有指定输出变量,则它不返回成功转换个数,而是返回成功转换的结果。
示例:
-
set num [scan "abcABC" "%c%c" var1 var2]
-
=> 2
-
-
puts "
var2"-
=> 97 98
-
-
set num [scan "abcABC" "%c%c"]
-
=> 97 98
-
-
puts $num
-
=> 97 98
-
-
scan "abcABC" {%[a-z]} res #格式描述说明要扫描小写的 a 到 z 区间的连续字符,用到了花括号表明是一个集合
-
=> 1
-
-
puts $res
-
=> abc
-
-
scan "ABCabc" {%[A-b]} res
-
=> 1
-
-
puts $res
-
=> ABCab
-
-
scan "ABCab" {%[^a-b]} res #匹配非a-b的字符, 字符^说明匹配所有不在集合中的字符
-
=> 1
-
-
puts $res
-
=> ABC
-
-
scan "ABCab" {%2[^a-b]} res #指定匹配字符数
-
=> 1
-
-
puts $res
-
=> AB
-
5. 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}
-
6. string命令
6.1 string命令列表
下表给出了各种 string 命令语法格式和说明:
命 令 | 说 明 |
string bytelength str | 返回用于存储字符串的字节数。 |
string compare ?-nocase? ?- length len? str1 str2 | 根据词典顺序比较字符串。 -nocase 选项表示大小写无关。 -length 选项表示只比较指定长度的开头部分字符。如果字符串相同就返回0(str1=str2),如果 str1 的顺序比 str2 靠前就返回-1( str1<str2),其他情况返回 1(str1>str2)。 |
string equal ?-nocase? str1 str2 | 比较字符串,相同返回 1,否则返回 0。 |
string first str1 str2 | 返回在 str2 中 str1 第一次出现的索引位置,如果没有找到则返回-1 |
string index str index | 返回指定位置的字符。 index 号从 0 开始。如果 index 为 end 则返回最后一个字符。 |
string is class ?-strict? ?-failindex varname? str | 判断字符串的类型,如果是指定类型就返回 1。字符类型例如有整型、布尔型等等。如果使用了-strict 则表示不匹配空字符,否则总是匹配的。如果指定了 failindex 则将 string 中非 class 的字符索引赋给varname 变量。 |
string last str1 str2 | 返回 str2 在 str1 最后一次出现的位置索引。没有搜索到就返回-1。 |
string length str | 返回 str 中的字符个数 |
string map ?-nocase? charMapstr | 返回根据 charMap 中输入、输出列表将 str 中的字符进行映射后而产生的新字符串。参见本节“字符串映射”部分。 |
string match pattern str | 如果 str 匹配 pattern 就返回 1,否则返回 0。使用的是通配风格的匹配。参见本节的“字符串的匹配”部分。 |
string range str index1 index2 | 返回 str 中从 index1 到 index2 之间的字符串。 |
string repeat str count | 返回将 str 重复 count 次的字符串。 |
string replace str firstlast ?newstr? | 将从 first 开始到 last 结束的一段字符串替换为 newstr 字符串。如果newstr 没有,则这部分字符串内容会被删除。 |
string tolower str ?first? ?last? | 将指定范围的字符转化为小写格式。 |
string totile str ?first? ?last? | 通过将第一个字符替换为 Unicode 的标题型字符或大写形式,而其余的替换为小写形式的方法将 str 转换为开始字母大写形式。可以用参数指定操作范围。 |
string toupperstring ?first? ?last? | 将指定范围的字符转化为大写形式。 |
string trim str ?chars? | 从 str 两端删除 chars 中指定的字符。 chars 默认为空字符。 |
string trimleft str ?chars? | 从 str 开头删除 chars 中指定的字符。 chars 默认为空字符。 |
string trimright str ?chars? | 从 str 结尾删除 chars 中指定的字符。 chars 默认为空字符。 |
string wordend str index | 返回 str 中在索引位置 index 包含字符的单词之后的字符的索引位置。 |
string wordstart str index | 返回 str 中在索引位置 index 包含字符的单词中第一个字符的索引位置 |
说明: 命令中的两个问号之间的内容是任选项,表示根据实际需要可选的内容。
6.2 字符串比较
我们在 expr 和控制语句如 if、 while 中可用比较运算符”==”、 ”!” 、 “=”、 “<”和“>”等来进行字符串比较,但是如不注意的话就会产生问题。首先必须用双引号来将字符串值括起来,这样表达式语法分析器才能按照字符串类型来进行识别。然后必须用花括号将整个表达式括起来以阻止主解释器将双引号去掉:
- if {$x == “true”} {puts ok}
然而,这样的直接比较还是会带来其他意想不到的问题。比较安全的方法是使用 string compare 和 string equal 来操作,而且这些 string 命令的执行速度也更快。
string compare 和 string equal 进行字符串比较的例子:
- set s1 abc
- => abc
- set s2 abd
- => abd
if {[string compare
puts "s1 is same as s2"
} else {
puts "s1 isn't same s2"
}
=> s1 isn't same s2
if {[string equal
puts "s1 is same as s2"
} else {
puts "s1 isn't same s2"
}
=> s1 isn't same s2
注意命令返回值: string compare 在不同的情况下返回 1,相同返回 0。而 string equal 和string match 则恰恰相反,相等或者匹配时返回 1 ,不同返回 0。
6.3 string match 字符串匹配
使用 string match 来匹配字符的结构:
字符 | 说明 |
* | 通配符。匹配任意数量和值的任意字符 |
? | 匹配一个字符 |
[chars] | 匹配 chars 中的任意一个字符 |
示例:
- string match a* alpha
- => 1
- string match ? XY
- => 0 #不匹配
- string match ?? XY # 一个”?”对应一个字符,为了匹配两个字符,必须输入两个问号
- => 1 #ok
6.4 字符串替换
string replace 可以用新的字符串代替字符串中指定范围内的字符,如果没有指定新字符串,则指定范围内的字符都会被删除。另外注意:替换不改变原来字符串变量的值,只是返回更改后的新字符串。
-
string replace aaaabbbb 1 3 ccc
-
=> acccbbbb
-
-
string replace aaaabbbb 1 3
-
=> abbbb
-
-
set a aaabbb
-
string replace $a 1 2
-
=> abbb
-
-
puts $a
-
=> aaabbb #a 的值并没有改变
-
6.5 字符类别(class)测试
string is 命令用来测试一个字符串是否属于某个特定的类( class)。它对于进行参数输入合法性检查非常有效。比如,要确保输入参数是整数,则可以这么做:
if {![string is integer $input]} {
error "Invalid input parameter: $input. Please enter a integer number" }
命令 string is 当正确时返回 1,不正确返回 0, ”!”是逻辑非操作。 error 命令和 puts 作用相似,但 error 会终止程序。
类是按照 Unicode 字符集定义的,它们要比 ASCII 编码方式指定范围的字符集更通用。下表列举了这些类:
字符类 | 说明 |
alnum | 任何字母或数字字符 |
alpha | 任何字母字符 |
ascii | 任何具有 7 位字符编码的字符(即,小于 128) |
boolean | 0, 1, true, false(不分大小写) |
control | 字符编码小于 32 而又不是 NULL 的字符 |
digit | 任何数字字符 |
double | 有效浮点数 |
false | 0, false(不分大小写) |
graph | 不包含空格字符在内的任何打印字符 |
integer | 有效整数 |
lower | 全为小写的字符串 |
alnum 的同义词 | |
punct | 任何标点符号 |
space | 空格符、制表符、换行符、回车、垂直制表、退格符 |
true | 1、 true(不分大小写) |
upper | 全为大写的字符串 |
wordchar | 字母、数字和下划线 |
4.6 字符串映射
string map 命令根据字符映射对字符串进行转换。映射以输入、输出表的形式表示。凡是字符串中包含有输入序列的地方都使用相应的输出序列替换。输入、输出要成对使用:
-
string map {f p d l} "food"
-
=> pool
-
上例命令中 {f p d l}为输入、输出表,输入、输出项成对出现: f、 d 为输入, p、 l 为输出,f对应 p,而 d 对应 l。命令的结果是字符串 food 中的 f 被 p 替换, d 被 l 替换。
输入和输出项可不止一个字符而且不要求长度相同:
-
string map {f pp d ll oo a} "food"
-
=> ppall
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端