我有一个字符串,我想它的部分转换为不同的整数variables.for比如我有字符串:“一些文字,0x0110,0XA0,0xFF时,0×02”TCL和分裂部分为整数
从这一点我想var1 = 0x02,var2 = 0xff,var3 = 0xa0,var4 = 0x02
任何人有任何使用tcl和字符串的经验,可以帮助我吗?
我有一个字符串,我想它的部分转换为不同的整数variables.for比如我有字符串:“一些文字,0x0110,0XA0,0xFF时,0×02”TCL和分裂部分为整数
从这一点我想var1 = 0x02,var2 = 0xff,var3 = 0xa0,var4 = 0x02
任何人有任何使用tcl和字符串的经验,可以帮助我吗?
假设
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试图评估方括号内的文本作为命令。
命令使用(链接到手册页):set,scan,join,concat,lrepeat,string,split,lrange,lassign,regexp。 *)杰克曼先生确实以这种方式签署了他的名字。在所有小写字母中写下别人的名字会感到奇怪和含糊不清,但是OTOH也改变了某人自己选择写他们的名字的方式,这也感觉不对。
提取的值与一个正则表达式
% 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
很好,只要真实的输入文字像条件那么好...... –
提到的手册页:https://www.tcl.tk/man/tcl/TclCmd/scan.htm – patthoyts
我更愿意把命令链接内联文字......但是否则这是一个非常好的答案。 –
@DonalFellows:我仍然试图为此制定个人表格。最初我偶尔提供链接,理由是如果他们可以编写程序,他们可以找到文档。最近我一直在重新思考这个问题,上面patthoyts的评论为实验提供了动力。文本中的链接和列表中的链接都有优点和缺点:我不知道我喜欢哪种风格。也许有关于这个地方的Meta讨论?嗯。噢,谢谢你的好话。 –