2014-02-28 88 views
1

我有一个字符串,我想它的部分转换为不同的整数variables.for比如我有字符串:“一些文字,0x0110,0XA0,0xFF时,0×02”TCL和分裂部分为整数

从这一点我想var1 = 0x02,var2 = 0xff,var3 = 0xa0,var4 = 0x02

任何人有任何使用tcl和字符串的经验,可以帮助我吗?

回答

3

假设

set str "some text,0x0110, 0xa0, 0xff, 0x02" 

如果你只想要的值,你可以使用这个命令,返回值的列表:

scan $str "some text,%x,%x,%x,%x" 
# -> 272 160 255 2 

(它要求scan命令来查找并提取4以逗号分隔的十六进制值字段(带有可选空格),前面带前缀字符串。)

如果要将这些值分配给变量directl y,像这样调用命令(在这种情况下,它返回读取的字段数,这是一件很好的事情要知道,因为任何数字都不等于您放入的字段数表示出现了问题):

scan $str "some text,%x,%x,%x,%x" var1 var2 var3 var4 
# -> 4 

如果你想存储的数值为十六进制文本,该命令可能会做:

scan $str {some text, %[^,], %[^,], %[^,], %[^,]} var1 var2 var3 var4 

(它指定字段应包括除逗号的字符,否则就和以前一样。在这种情况下,需要在格式字符串之前指定逗号后的空格:空格字符表示应该跳过零个或多个空格,制表符或换行符。括号是必要的,以防止Tcl的从解释方括号作为嵌入命令)

另一个变体:

scan $str {some text, %[xX0-9a-fA-F], %[xX0-9a-fA-F], %[xX0-9a-fA-F], %[xX0-9a-fA-F]} var1 var2 var3 var4 

(这一个指定每个字段作为由完全相同的字符x(上部或下部的一个串情况下)和十六进制数字,以某种顺序)。

这有点笨拙。你可以通过从零件中构建它来使其复杂一点:

set X {%[xX0-9a-fA-F]} 
# -> %[xX0-9a-fA-F] 
set fmt [join [concat {{some text}} [lrepeat 4 $X]] {, }] 
# -> some text, %[xX0-9a-fA-F], %[xX0-9a-fA-F], %[xX0-9a-fA-F], %[xX0-9a-fA-F] 
scan $str $fmt var1 var2 var3 var4 

有更多的方法可以做到这一点。你不能直接将它分成列表,因为split $str {, }将分割为逗号或空格,而不是字符串逗号+空格(嗯,你可以可以,但它不是很方便)。但是:如果您第一次将所有逗号+空格的字符串,只是逗号,split变成有用:

string map {{, } ,} $str 
# -> some text,0x0110,0xa0,0xff,0x02 
split [string map {{, } ,} $str] , 
# -> {some text} 0x0110 0xa0 0xff 0x02 
lrange [split [string map {{, } ,} $str] ,] 1 end 
# -> 0x0110 0xa0 0xff 0x02 

导致:

lassign [lrange [split [string map {{, } ,} $str] ,] 1 end] var1 var2 var3 var4 

它给你你想要的分配。

我在想是否要解释基于正则表达式的提取,但现在我看到glenn jackman *已经做到了。只是为了完整性,我会添加它的一个简短的提到我的答案太多,但我基本上很少有说以后他做了什么:

regexp -inline -all -- {0[xX][[:xdigit:]]+} $str 
# -> 0x0110 0xa0 0xff 0x02 
lassign [regexp -inline -all -- {0[xX][[:xdigit:]]+} $str] var1 var2 var3 var4 

我的定义和格伦之间的一些差异。他使用的是字锚(\m\M),这在这里似乎不是非常必要(但在某些特殊情况下可能会证明是有用的:使用它们肯定没有错)。他还与十六进制数字的前缀x相匹配:我倾向于匹配大写或小写x([xX])。实际上,十六进制文字几乎总是写成0x...,但你永远无法确定。所以这些差异归结为他希望以某种方式做出额外的确定,并且我希望在另一个方面更加确定。

regexp调用说返回匹配(-inline)的列表,以匹配正则表达式(-all)的所有事件和来匹配由零字符(0)的字符串,然后由上部或小写x字符([xX]),后面跟一个或多个(+)出现的([ ... ])十六进制数字([:xdigit:])。同样,表达式中的大括号可以防止Tcl试图评估方括号内的文本作为命令。

命令使用(链接到手册页):setscanjoinconcatlrepeatstringsplitlrangelassignregexp。 *)杰克曼先生确实以这种方式签署了他的名字。在所有小写字母中写下别人的名字会感到奇怪和含糊不清,但是OTOH也改变了某人自己选择写他们的名字的方式,这也感觉不对。

+0

提到的手册页:https://www.tcl.tk/man/tcl/TclCmd/scan.htm – patthoyts

+0

我更愿意把命令链接内联文字......但是否则这是一个非常好的答案。 –

+0

@DonalFellows:我仍然试图为此制定个人表格。最初我偶尔提供链接,理由是如果他们可以编写程序,他们可以找到文档。最近我一直在重新思考这个问题,上面patthoyts的评论为实验提供了动力。文本中的链接和列表中的链接都有优点和缺点:我不知道我喜欢哪种风格。也许有关于这个地方的Meta讨论?嗯。噢,谢谢你的好话。 –

2

提取的值与一个正则表达式

% set s "some text,0x0110, 0xa0, 0xff, 0x02" 
some text,0x0110, 0xa0, 0xff, 0x02 
% set xnums [regexp -inline -all {\m0x[[:xdigit:]]+\M} $s] 
0x0110 0xa0 0xff 0x02 
% lassign $xnums var1 var2 var3 var4 
+0

很好,只要真实的输入文字像条件那么好...... –