当前位置: 首页 > 编程笔记 >

tcl 不带括号的表达式的问题

刘明朗
2023-03-14
本文向大家介绍tcl 不带括号的表达式的问题,包括了tcl 不带括号的表达式的问题的使用技巧和注意事项,需要的朋友参考一下

示例

将表达式字符串参数作为大括号字符串提供是一种好习惯。标题“双重替代”概述了背后的重要原因。

该expr命令评估基于运算符的表达式字符串以计算值。该字符串是根据调用中的参数构造的。

expr 1 + 2    ; # three arguments
expr "1 + 2"  ; # one argument
expr {1 + 2}  ; # one argument

这三个调用是等效的,并且表达式字符串相同。

命令if,for和while使用相同的求值器代码作为条件参数:

if {$x > 0} ...
for ... {$x > 0} ... ...
while {$x > 0} ...

主要区别在于条件表达式字符串必须始终为单个参数。

与Tcl中命令调用中的每个参数一样,内容可能会也可能不会被替换,具体取决于如何对它们进行引用/转义:

set a 1
set b 2
expr $a + $b   ; # expression string is {1 + 2}
expr "$a + $b" ; # expression string is {1 + 2}
expr \$a + \$b ; # expression string is {$a + $b}
expr {$a + $b} ; # expression string is {$a + $b}

第三和第四种情况有所不同,因为反斜杠/花括号阻止替换。结果仍然是相同的,因为内部的求值器expr本身可以执行Tcl变量替换并将字符串转换为{1 + 2}。

set a 1
set b "+ 2"
expr $a $b   ; # expression string is {1 + 2}
expr "$a $b" ; # expression string is {1 + 2}
expr {$a $b} ; # expression string is {$a $b}: FAIL!

在这里,我们遇到了带有括号的参数的麻烦:当评估器expr执行替换时,表达式字符串已被解析为运算符和操作数,因此评估者看到的是一个由两个操作数组成的字符串,它们之间没有运算符。(错误消息是“ missing operator at _@_ in expression "$a _@_$b"”。)

在这种情况下,expr调用之前的变量替换可以防止错误。支撑参数可以防止变量替换,直到表达式求值,这会导致错误。

可能会发生这种情况,最典型的情况是将要求值的表达式作为变量或参数传入。在这些情况下,除了保留参数不加括号之外,没有其他选择,允许参数评估程序“解包”表达式字符串以传递给expr。

但是,在大多数其他情况下,将表达式括起来并没有害处,并且确实可以避免很多问题。一些例子:

双重替代

set a {[exec make computer go boom]}
expr $a      ; # expression string is {[exec make computer go boom]}
expr {$a}    ; # expression string is {$a}

无括号的形式将执行命令替换,该命令替换会以某种方式破坏计算机(或加密或格式化硬盘或您所拥有的东西)。大括号形式将执行变量替换,然后尝试(失败)创建字符串“ [exec make computer go boom]”。避免了灾难。

无休止的循环

set i 10
while "$i > 0" {puts [incr i -1]}

此问题同时影响for和while。尽管看起来该循环将倒数至0并退出,但while的条件参数实际上始终10>0是因为while激活命令时该参数被评估为该参数。将参数括起来后,它将作为传递给while命令$i>0,并且该变量将为每次迭代替换一次。使用此代替:

while {$i > 0} {puts [incr i -1]}

总体评价

set a 1
if "$a == 0 && [incr a]" {puts abc}

a运行这段代码后,值是多少?由于&&运算符仅在左操作数为true时才对右操作数求值,因此该值仍应为1。但实际上,它的值为2。这是因为在求值表达式字符串时,参数evaluator已经执行了所有变量和命令替换。使用此代替:

if {$a == 0 && [incr a]} {puts abc}

定义了多个运算符(逻辑连接词||和&&,以及条件运算符?:)以求值其所有操作数,但只有在表达式字符串加括号时它们才能按设计工作。

 类似资料:
  • 问题内容: 在Java中,我试图编写一个与数学表达式中的一个单元匹配的正则表达式,即运算符之间的内容 我的意思是,在类似1 + [1 + 2]的表达式中,正则表达式应匹配前1个,然后匹配[1 + 2]。 我所拥有的是* [([-+]?\ d +(\。\ d +)?)(\ [。+ \])] * 其中([-+]?\ d +(\。\ d +)?)应该匹配任何数字,并且 (\ [。+ \]) 应该匹配括号

  • 我正在使用这段代码使用正则表达式拆分字符串 该代码适用于我拥有的几乎所有字符串,但我面临着这两个字符串的问题:和。似乎模式不匹配,我认为是因为特殊字符和。 我的预期结果和。

  • 我有一个非常好的正则表达式,它从文本中选择引用: 但是我需要一个正则表达式,它从没有引号的文本中选择引号。 例如,我有: 鲸鱼包括八个现存的家族:“鲸豚科”(白鲸),“鲸豚科”(露脊鲸),“鲸豚科”(侏儒露脊鲸),“白鲸科”(灰鲸),“独角鲸科”(白鲸和独角鲸),“抹香鲸科”(抹香鲸)。。。 我需要在引号之间提取文本: 龟甲翅目,龟甲翅目,龟甲翅目,... 要提取括号之间的文本,我使用正则表达式:

  • 本文向大家介绍python正则表达式中的括号匹配问题,包括了python正则表达式中的括号匹配问题的使用技巧和注意事项,需要的朋友参考一下 问题: m = re.findall('[0-9]*4[0-9]*', '[4]') 可以匹配到4. m = re.findall('([0-9])*4([0-9])*', '[4]') 匹配不到4. 这是为什么呢?PS,这个是一个简化的说明,我要用的正则比这

  • 我需要通过不在括号中的管道拆分文本。这是示例文本 我在这里找到了这个/\ |(?![^{]*})/g:regex,提取字符串,不要在两个括号之间 现在当我想用管子分割这部分字符串时 它还选择杰森、玛丽亚和圣诞老人之间的管道,因为它们后面有一个开口支架。如果正则表达式不在任何括号中,如何将其更改为仅匹配管道。 测试字符串: 应该返回 . 应该返回

  • 问题内容: 匹配字符串中的’(’的正则表达式是什么? 以下是场景: 我有一串 我想使用正则表达式拆分字符串。为此,我正在使用 但是我收到以下异常。 转义似乎不起作用。 问题答案: 两种选择: 首先,你可以使用转义 回 斜线- 另外,由于它是单个字符,因此您可以将其放入不需要转义的字符类中-