TCL字符串操作
|---|
| |
字符串操作
TCL 把所有的输入都当作字符串看待,所以 TCL 提供了较强的字符串操作功能,TCL 中与字符串操作有关的命令 string、format、regexp、regsub、scan 等
format 和 scan
format 命令类似于 C 语言中的 print 命令,用于格式化输出一些内容。
语法:
shell
format formatstring ?vlue value...?
示例:
shell
%set name john
John
%set age 20
20
%set msg [format "%s is %d years old" $name $age]
john is 20 years old
puts [format "My name is ${name}, I'm ${age} years old."]
scan 命令的语法如下:
shell
scan string format varName ?varName ...?
scan 命令可以认为是 format命令的逆,其功能类似于 C 语言中的 scanf 函数。它按 format 提供的格式分析 string 字符串,然后把结果存到变量 varName 中,注意除了空格和 TAB 键之外,string 和 format 中的字符和'%'必须匹配。
scan 命令的返回值是匹配的变量个数
示例:
shell
% scan "some 26 34" "some %d %d" a b
2
% set a
26
% set b
34
% scan "12.34.56.78" "%d.%d.%d.%d" c d e f
4
% puts [format "the value of c is %d,d is %d,e is %d ,f is %d" $c $d $e $f]
the value of c is 12,d is 34,e is 56 ,f is 78
format 和 scan 命令中使用的特殊符号的含义如下:
| 符号 | 含义 |
|---|---|
%s |
普通字符串 |
%d |
整数 |
%.2f |
浮点数,2是小数点后两位 |
%c |
字符 |
%o |
八进制 |
%x |
十六进制 |
regexp
resub
string
string 命令具有强大的操作字符串的功能,其中的 option 选项多达 20 个,部分常用的选用如下所述。
compare
shell
string compare ?-nocase? ?-length int? string1 string2
把字符串 string1 和 string2 根据字典顺序进行比较,如果字符串相同则返回0,如果 str1 的顺序比 str2 靠前就返回 -1,对于其它情况返回1。
如果有 -length 参数,那么只比较前 int 个字符,如果 int 为负数,那么这个参数被忽略。
如果有 -nocase 参数,那么比较时不区分大小写。
equal
shell
string equal ?-nocase? ?-length int? string1 string2
把字符串 string1 和 string2 进行比较,如果两者相同,返回值为 1,否则返回 0。
其他参数和 string compare 相同
match
shell
string match ?-nocase? pattern string
如果 pattern 匹配 string,那么返回 1,否则返回 0。
如果有 -nocase 参数,那么就不区分大小写.
在 pattern 中可以使用通配符:
*匹配 string 中的任意长的任意字符串,包括空字符串.?匹配 string 中任意单个字符[chars]匹配字符集合 chars 中给出的任意字符,其中可以使用 A-Z 这种形式\x匹配单个字符 x,使用\是为了让 x 可以为字符*、-、[、]
示例:
shell
% string match {a[b-f]cdef} abcdef
1
# 注意一定要用'{',否则 TCL 解释器会把 b-f 当作命令名,从而导致错误
index
shell
string index ${srting} charIndex
返回字符串中第 charIndex 个字符(0-based)。charIndex 可以是下面的值:
整数 n : 字符串中第 n 个字符(0-based)
end : 最后一个字符
end-整数 n :倒数第 n 个字符。string index "abcd" end-1 返回字符'c'
如果 charIndex 小于 0,或者大于字符串 string 的长度,那么返回空。
range
shell
string range ${srting} first last
返回字符串中从第 first 个到第 last 个字符的子字符串(0-based)。如果 first<0,那么first 被看作 0,如果 last 大于或等于字符串的长度,那么 last 被看作 end,如果 first 比 last大,那么返回空。
map
string map 是一个用于字符串替换的命令,它可以按照指定的映射关系替换字符串中的字符或子字符串。
shell
string map {old1 new1 old2 new2 ...} string
该命令可以将 string 中所有出现的 old1 替换为 new1,old2 替换为 new2,依此类推。
默认情况下,区分大小写;未匹配到 old,则不会发生替换。
map 命令的替换是严格按顺序执行的,并且后续映射不会影响已替换的部分,如下所示:
shell
# Example 1
set str "abc"
set new_str [string map {a 1 b 2 ab x} $str]
puts $new_str ;# 输出: 12c(先替换 a→1,b→2,ab 未被匹配)
# Example 2
# 先替换 "a" 为 "b",再替换 "b" 为 "c"
set new_str [string map {a b b c} "aabb"]
puts $new_str ;# 输出: bbcc(而非预期中的 cccc)
高级用法:
① 动态生成映射列表
映射列表可以通过变量或表达式动态生成:
shell
set replacements {a 1 b 2 c 3}
set str "a-b-c"
set new_str [string map $replacements $str]
puts $new_str ;# 输出: 1-2-3
② 删除字符
将 new 设为空字符串可实现删除操作:
shell
set str "Hello, 123 World!"
set new_str [string map {, "" " " ""} $str]
puts $new_str ;# 输出: Hello123World!
|---|
| |
文件操作
TCL 提供了丰富的文件操作的命令。通过这些命令你可以对文件进行操作,以顺序或随机方式读写文件,检索系统保留的文件信息(如最后访问时间)。
基本读写操作
TCL 中使用 open 打开文件,其基本用法如下,其中 access 是文件的打开方式。
shell
open file_name ?access?
文件的打开方式有如下几种:
| 选项 | 作用 |
|---|---|
r |
只读方式打开,文件已经存在,(默认方式) |
r+ |
读写方式打开,文件必须已经存在 |
w |
只写方式打开文件,如果文件存在则清空文件内容,否则创建一个新的空文件 |
w+ |
读写方式打开文件,如果文件存在则清空文件内容,否则创建一个新的空文件 |
a |
只写方式打开文件,文件必须存在,并把指针指向文件结尾(追加) |
a+ |
只读方式打开,并把指针指向文件尾。如果文件不存在,创建新的空文件 |
open 命令返回一个字符串用于表示打开的文件,所以真正的文件打开方式为如下,其中 fileID 是文件标识符。
shell
set fileID [open filename r]
当调用别的命令(gets,puts,close)对打开的文件进行操作时,就可以使用这个文件标识符。
TCL 有三个特定的文件标识:stdin,stdout,stderr,分别对应标准输入、标准输出和错误通道,任何时候都可以使用这三个文件标识。
TCL 中使用 gets 或 read 命令读取文件内容,使用 puts 命令进行写文件操作。
默认文件输入输出方式是连续的:即每个 gets 或 read 命令返回的是上次 gets 或 read 访问位置后面的字节,每个 puts 命令写数据是接着上次 puts 写的位置接着写。
使用 open 命令打开文件,并完成相关操作之后,通常需要使用 close 命令关闭文件:
shell
close ${fileID}
读文件:
gets 命令逐行读取文件,忽略行尾的换行符,其基本用法如下:
shell
gets fileId ?varName?
fileId 是使用 open 命令打开文件时指定的文件标识符。
如果命令中有 varName 就把该行赋给它,并返回该行的字符数(文件尾返回-1);如果没有 varName 参数,返回文件的下一行作为命令结果(如果到了文件尾,就返回空字符串)
shell
set f [open $filename r]
while { [gets $f line ] } {
if {[regexp $pattern $line]} {
puts stdout $line
}
}
close $f
写文件:
使用 puts 命令进行写文件操作,其基本用法如下:
shell
puts ?-nonewline? ?fileId? string
puts 命令把 string 写到 fileId 中,如果没有 nonewline 选型,该命令会自动添加换行符,即每次写一行。
该命令的返回值为一空字符串。
puts 命令使用 C 的标准 I/O 库的缓冲区方案,这就意味着使用 puts 产生的信息不会立即出现在目标文件中。如果你想使数据立即出现在文件中,那你就调用 flush 命令:
shell
flush fileId; # 把缓冲区内容写到 fileId 标识的文件中,命令返回值为空字符串。
文件查找
TCL 中 glob 命令用来对文件名进行操作,例如,glob *.c *.h 的作用是返回当前目录中所有以.c 或.h 为后缀的文件的名称。
基本语法:
glob 命令的基本语法如下:
shell
glob ?options? pattern ?pattern ...?
常用选项:
| 选项 | 作用 |
|---|---|
-nocomplain |
当没有匹配项时返回空列表。没有-nocomplain 时,如果结果是空的,就返回错误 |
-directory <dir> |
指定搜索的基准目录 |
-types <type> |
过滤文件类型(d=目录, f=普通文件, l=链接等) |
-tails |
返回相对于基准目录的文件名(需配合 -directory 使用)(只有文件名,没有路径) |
-path |
强制将 pattern 视为路径(处理包含 / 的复杂 pattern 时使用) |
-- |
标记选项结束,后续参数均为匹配 pattern(处理以 - 开头的文件名时使用) |
示例1:判断文件是否存在
TCL 中有很多命令来判断一个文件是否存在。
方法1 :使用 file exists 命令
shell
if { [file exists $filename] } {
puts "文件存在"
} else {
puts "文件不存在"
}
方法2 :使用 glob 命令
shell
set files [glob -nocomplain $filename]
if { [llength $files] > 0 } {
puts "文件存在"
} else {
puts "文件不存在"
}