好吧,这个问题把我绕晕了。Arch 上的 Tcl 9.0,跑的是 tclsh main.tcl,给客户的五金供应网站做的一个小订单报表。
我在 config.tcl 里原本只有一条规则 (total >= 200),一切正常。后来我加了第二条规则,让带客户备注的订单也被标记出来。
set ::flag_rules {
{total >= 200}
{note ne {}}
}
现在程序跑到一半就挂了,报 invalid command name "Dana"。栈追踪指向 rule_match 里的 expr 那一行。
proc rule_match {row rule} {
lassign $rule field op value
set have [dict get $row $field]
return [expr "\"$have\" $op \"$value\""]
}
我的代码里根本没有叫 "Dana" 的命令,它出现在数据里。金额比较大的订单里有一条,在 orders.tsv 中的备注是这样的。
1003 Petrakis Plumbing 1250.75 call [Dana] before shipping
其他备注 (比如 "leave at side door") 都能正常通过。我在崩溃前一刻把这一行的 dict 打印出来了,看起来完全正常。制表符切得没问题,四个字段都在,备注也是完整的。所以我已经对着 load_orders 折腾了一个小时,一直以为是客户导出的文件有什么奇怪的编码问题或者混进了多余的字节。我还在 Neovim 里用 :set list 看过,制表符就是制表符。(顺便问一句,为什么他们导出的文件里,空备注的行末尾多了一个制表符,而 1005 那行没有?这是另一个问题,改天再说。)
我想不通的是,一个躺在 dict 里的字符串是怎么变成命令调用的。没有任何地方对它做 eval 啊。为什么只有这一行出问题?
从英语翻译·查看原文Okay, this one has me chasing my tail. Tcl 9.0 on Arch, tclsh main.tcl, small order report for a client's hardware-supply site.
I had one rule in config.tcl (total >= 200) and everything was happy. Then I added a second rule so orders with a customer note get flagged too:
set ::flag_rules {
{total >= 200}
{note ne {}}
}
Now the run dies partway through with invalid command name "Dana". The trace points at the expr line in rule_match:
proc rule_match {row rule} {
lassign $rule field op value
set have [dict get $row $field]
return [expr "\"$have\" $op \"$value\""]
}
"Dana" isn't a command anywhere in my code. It's in the data. One of the bigger orders has this note in orders.tsv:
1003 Petrakis Plumbing 1250.75 call [Dana] before shipping
Other notes (like "leave at side door") go through fine. I printed the row dict right before the crash and it looks totally normal. Tabs split right, all four fields in place, note intact. So I've been poking at load_orders for an hour, convinced the client's export has some weird encoding thing or a stray byte. Checked in Neovim with :set list, tabs look like tabs. (Side note: why does their export have a trailing tab on the empty-note rows but not on 1005? Different problem, different day.)
What I can't see is how a string sitting in a dict becomes a command call. Nothing evals it. Why only this row?