我想将一个字符串参数传递给tcl过程,而不将括号内容解释为命令,也不使用\来转义括号。例如:
proc resolve_signal_path {signal_path} {
puts $signal_path
# Replace [] with ():
set signal_path [string map -nocase {"[" "(" "]" ")"} $signal_path]
return $signal_path
}
puts [resolve_signal_path abc[0]]
这会产生“无效的命令名称”0“”错误。我怎么能传递这样的论点? 我试过单引号''围绕论证无济于事。
更新:特别是有一种方法可以处理这个问题,如果参数是一个列表而不是一个字符串,它来自于读取文件行:
proc resolve_signal_path {args} {
set signal_name [lindex $args 0]
puts $signal_name
# Replace [] with ():
set signal_path [string map -nocase {"[" "(" "]" ")"} $signal_name]
return $signal_path
}
# The following "fileline" comes from reading a file so I cannot change it
# fileline: abc[0] 2nd 3rd
puts [resolve_signal_path $fileline]
我如何传递这个'fileline'变量,它是一个字符串列表,考虑到它包含[]?
答案 0 :(得分:2)
Tcl使用[
... ]
来表示命令替换,除非你以某种方式引用它。有几种方法可以进行引用,例如使用各种反斜杠序列(其中\[
... \]
到目前为止最简单),但最好的方法是把整个论点放在{
大括号}
中,因为它只是抑制所有这些替换(包括反斜杠和变量替换):
puts [resolve_signal_path {abc[0]}]
puts [resolve_signal_path abc\[0\]]
Tcl 没有做的是给你一种说法“选择不对命令的特定参数进行替换”的方法,因为它正式没有查找意味着/执行命令,直到它已经处理了替换。在这种情况下,您需要使用subst
来获得选择性(它可能是您可能在命令中隐藏的那种东西,但这会变得更加复杂):
puts [resolve_signal_path [subst -nocommands {$name[0]}]]
说实话,我经常不经常使用这种东西。使用大括号,偶尔使用反斜杠,效果非常好。
在更新的问题中,还需要考虑一些额外的事情。
[
和]
字符对列表不是实际特殊,但Tcl的list- 生成命令会引用它们反正。args
形式参数是特殊的(当它是最后一个参数时)并且始终包含(剩余)参数的列表。这意味着,如果$fileline
本身就是一个列表,则需要通过两个级别的list-ishness。list
,lrepeat
,lappend
等。在解析常规字符串以获取列表时,scan
,regexp
和split
都可以返回列表,也可以在正确的情况下使用。所以,我用这样的东西解析abc[0] 2nd 3rd
:
set words [regexp -inline -all {\S+} $line]
因为这将选择性地规范化间距并添加所需的任何引用。 (在这种情况下,它会将输入转换为{abc[0]} 2nd 3rd
。)您需要准确排序与$line
对应的值 - 我不太确定您的代码 - 但是完成列表转换后,您可以安全地使用lindex
来挑选单个单词,无论他们曾经拥有过什么字符。
set signal_name [lindex $words 0]
# It'll now be exactly “abc[0]”
解析通常是理解可能具有什么输入的问题,并使代码能够轻松地实际理解输入的内容。这听起来很简单。