Tcl:将带方括号的参数传递给过程

时间:2016-12-21 11:21:46

标签: tcl

我想将一个字符串参数传递给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'变量,它是一个字符串列表,考虑到它包含[]?

1 个答案:

答案 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。
  • 从替换片段构建列表时,请始终使用列表生成命令,例如listlrepeatlappend等。在解析常规字符串以获取列表时,scanregexpsplit都可以返回列表,也可以在正确的情况下使用。

所以,我用这样的东西解析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]”

解析通常是理解可能具有什么输入的问题,并使代码能够轻松地实际理解输入的内容。这听起来很简单。

相关问题