我有一个字符串,我想将它的一部分转换为不同的整数变量。例如我有字符串:“some text,0x0110,0xa0,0xff,0x02”
从这一点开始我希望var1 = 0x02,var2 = 0xff,var3 = 0xa0,var4 = 0x02
任何人都有使用tcl和字符串的经验,可以帮助我吗?
答案 0 :(得分:3)
假设
set str "some text,0x0110, 0xa0, 0xff, 0x02"
如果您只想要这些值,可以使用此命令返回值列表:
scan $str "some text,%x,%x,%x,%x"
# -> 272 160 255 2
(它要求scan
命令查找并提取由逗号分隔的四个十六进制值字段(带有可选的空格),并以前缀字符串开头。)
如果要直接将这些值分配给变量,请调用这样的命令(在这种情况下,它会返回读取的字段数,这是一件好事,因为任何数字都不等于你的字段数放入表示出现了问题):
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
我的定义与glenn之间存在一些差异。他正在使用单词锚(\m
和\M
),这在这里似乎并不十分必要(但在一些奇特的情况下可能会有用:使用它们当然没有错)。他还匹配十六进制数前缀中的文字x
:我更喜欢匹配大写或小写x([xX]
)。在实践中,十六进制文字几乎总是写成0x...
,但你永远不能确定。因此,差异归结为他想要以一种方式更加确定,而我希望在另一种方式中更加确定。
调用regexp
表示返回匹配列表(-inline
),以匹配正则表达式(-all
)的所有匹配项,并匹配包含的匹配项零个字符(0
),后跟大写或小写x字符([xX]
),后跟一个或多个(+
)次出现的{[
.. 。]
)十六进制数字([:xdigit:]
)。同样,表达式周围的大括号阻止Tcl尝试将方括号内的文本作为命令进行评估。
使用的命令(指向手册页的链接):set,scan,join,concat,lrepeat,{ {3}},string,split,lrange,lassign。
*)杰克曼先生确实签了他的名字。在所有小写字母中写下别人的名字感觉很奇怪而且含糊不清,但OTOH改变别人自己选择写名字的方式也感觉不对。
答案 1 :(得分: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