为什么 expr $a eq $b 会因 "invalid bareword" 而失败?

Why does expr $a eq $b fail with "invalid bareword"?

我有 TCL 8.6,下面的代码工作正常:

set a abc
set b abcd
if {$a eq $b} {puts hi}

但以下是我的错误:

set a abc
set b abcd
expr $a eq $b

invalid bareword "abc"
in expression "abc eq abcd";
should be "$abc" or "{abc}" or "abc(...)" or ...

请问这是怎么回事? if命令中的条件表达式和expr命令中的表达式不一样吗?

不,不一样。您看到的和 expr 看到的是不同的,即它将尝试评估的字符串。这是因为命令调用的每个单词(就像 Tcl 中的每个命令调用一样)在执行命令之前都经过替换。

第一种情况:大括号防止表达式的内容被过早替换。你看{$a eq $b}expr$a eq $b。这是两个操作数($a$b)和一个运算符(eq):expr 可以使用它。

第二种情况:三个参数在传递给expr之前被代入。你看$a eq $bexprabc eq abcd。那是两个无意义的值和一个运算符,expr 无法处理。

如果在 expr 表达式中有一个字符串不是布尔值或运算符的名称,它应该是变量替换 ($abc) 的一部分,或者函数名称 (abc(...)),或命令替换的一部分 ([... abc ...]),或者明确引用 ("abc"{abc})。

始终将参数括起来 expr。这样做可以防止很多问题,这个是比较温和的问题之一。

文档:expr