|
问题7: 如何用TCL的内嵌脚本命令处理字符串(续1)
1. regexp命令
语法:regexp ?switchs? exp string ?matchVar? ?subMatchVar subMatchVar...?
regexp命令用于判断正规表达式exp是否全部或部分匹配字符串string,匹配返回1,否则0。
在正规表达式中,一些字符具有特殊的含义:
. 匹配任意单个字符
^ 表示从头进行匹配
$ 表示从末尾进行匹配
\x 匹配字符x,这可以抑制字符x的含义
[chars] 匹配字符集合chars中给出的任意字符,如果chars中的第一个字符是^,表示匹配任意不在chars中的字符,chars的表示方法支持a-z之类的表示。
(regexp) 把regexp作为一个单项进行匹配
* 对*前面的项0进行次或多次匹配
+ 对+前面的项进行1次或多次匹配
? 对?前面的项进行0次或1次匹配
regexp1|regexp2 匹配regexp1或regexp2中的一项
下面这个例子是从《Tcl and Tk ToolKit》中摘下来的:
^((0x)?[0-9a-fA-F]+|[0-9]+)$
这个正规表达式表示匹配任何十六进制或十进制的整数。
两个正规表达式以|分开(0x)?[0-9a-fA-F]+和[0-9]+,表示可以匹配其中的任何一个,事实上前者匹配十六进制,后者匹配的十进制。
^表示必须从头进行匹配,从而上述正规表达式不匹配jk12之类不是以0x或数字开头的串。
$表示必须从末尾开始匹配,从而上述正规表达式不匹配12jk之类不是数字或a-fA-F结尾的串。
下面以(0x)?[0-9a-fA-F]+ 进行说明,(0x)表示0x一起作为一项,?表示前一项(0x)可以出现0次或多次,[0-9a-fA-F]表示可以是任意0到9之间的单个数字或a到f或A到F之间的单个字母,+表示象前面那样的单个数字或字母可以重复出现一次或多次。
% regexp {^((0x)?[0-9a-fA-F]+|[0-9]+)$} ab
1
% regexp {^((0x)?[0-9a-fA-F]+|[0-9]+)$} 0xabcd
1
% regexp {^((0x)?[0-9a-fA-F]+|[0-9]+)$} 12345
1
% regexp {^((0x)?[0-9a-fA-F]+|[0-9]+)$} 123j
0
如果regexp命令后面有参数matchVar和subMatchVar,则所有的参数被当作变量名,如果变量不存在,就会被生成。 regexp把匹配整个正规表达式的子字符串赋给第一个变量,匹配正规表达式的最左边的子表达式的子字符串赋给第二个变量,依次类推,例如:
% regexp { ([0-9]+) *([a-z]+)} " there is 100 apples" total num word
1
% puts " $total ,$num,$word"
100 apples ,100,apples
regexp可以设置一些开关(switchs〕,来控制匹配结果:
-nocase 匹配时不考虑大小写
-indices 改变各个变量的值,这是各个变量的值变成了对应的匹配子串在整个字符串中所处位置的索引。例如:
% regexp -indices { ([0-9]+) *([a-z]+)} " there is 100 apples" total num word
1
% puts " $total ,$num,$word"
9 20 ,10 12,15 20
正好子串“ 100 apples”的序号是9-20,"100"的序号是10-12,"apples"的序号是15-20
-- 表示这后面再没有开关 (switchs〕了,即使后面有以'-'开头的参数也被当作正规表达式的一部分。
2. regsub命令
语法:regsub ?switchs? exp string subSpec varname
regsub的第一个参数是一个整个表达式,第二个参数是一个输入字符串,这一点和regexp命令完全一样,也是当匹配时返回1,否则返回0。不过regsub用第三个参数的值来替换字符串string中和正规表达式匹配的部分,第四个参数被认为是一个变量,替换后的字符串存入这个变量中。例如:
% regsub there "They live there lives " their x
1
% puts $x
They live their lives
这里there被用their替换了。
regsub命令也有几个开关(switchs):
-nocase 意义同regexp命令中。
-all 没有这个开关时,regsub只替换第一个匹配,有了这个开关,regsub将把所有匹配的地方全部替换。
-- 意义同regexp命令中。 |
|