字符串

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]  #\用来引用符号2,即取第二个元素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 "var1var2"

    •  => 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 靠前就返回-1str1<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 和控制语句如 ifwhile 中可用比较运算符”==””!” “=”“<”“>”等来进行字符串比较,但是如不注意的话就会产生问题。首先必须用双引号来将字符串值括起来,这样表达式语法分析器才能按照字符串类型来进行识别。然后必须用花括号将整个表达式括起来以阻止主解释器将双引号去掉:

  • 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 s1s2] == 0} {

  puts "s1 is same as s2"

} else {

  puts "s1 isn't same s2"

}

 => s1 isn't same s2

if {[string equal s1s2]} {

  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 01truefalse(不分大小写)
control 字符编码小于 32 而又不是 NULL 的字符
digit 任何数字字符
double 有效浮点数
false 0false(不分大小写)
graph 不包含空格字符在内的任何打印字符
integer 有效整数
lower 全为小写的字符串
print alnum 的同义词
punct 任何标点符号
space 空格符、制表符、换行符、回车、垂直制表、退格符
true 1true(不分大小写)
upper 全为大写的字符串
wordchar 字母、数字和下划线

4.6 字符串映射 

string map 命令根据字符映射对字符串进行转换。映射以输入、输出表的形式表示。凡是字符串中包含有输入序列的地方都使用相应的输出序列替换。输入、输出要成对使用

  • string map {f p d l} "food"

    •  => pool

 

上例命令中 {f p d l}为输入、输出表,输入、输出项成对出现: fd 为输入, pl 为输出,f对应 p,d 对应 l。命令的结果是字符串 food 中的 f p 替换, d l 替换。

输入和输出项可不止一个字符而且不要求长度相同  

  • string map {f pp d ll oo a} "food"

    •  => ppall 

       
posted @   小熊酱  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示