"$(($i++))"背后的魔力是什么?



这是一小段代码,以 1 秒的间隔输出1 2 3 ...

while ($true) {
sleep -s 1
"$(($i++))"
}

怎么可能?

评论中有很好的指示,但让我更深入地挖掘:

$i++解释

  • $i++使用递增运算符++将变量$i的值递增1,这在C#和C/C++等语言中可能很熟悉。 正如预期的那样,也存在一个互补递减运算符--)。

    • 由于++位于变量(后缀形式)之后,因此在语句中使用变量的值后会发生递增。
      将其放在变量 -++$i(前缀形式)之前首先执行递增。
      如果单独使用递增/递减操作,则这种区别无关紧要。

    • 假定$i包含数值类型的实例,否则会发生错误;如果变量$i尚未初始化,则其值实际上$null,PowerShell 强制[int]类型0。因此,$i++在其语句的上下文中计算为0,并在之后递增为1

  • 增/递减表达式(如$i++)被视为赋值- 你可以将其视为$i = $i + 1-PowerShell 中的赋值不产生任何输出(它们不返回任何内容;它们只更新变量的值)。

$i++周围(...)的解释

  • 通过将赋值括在括号((...))中,分组 运算符,您可以将其转换为表达式,这意味着赋值的值被传递,以便它可以参与更大的表达式;例如:

    • $i = 0......没有输出 - 只是将值0分配给变量$i
    • ($i = 1)......输出1:由于(...),分配的值也被输出。
    • (++$i)......pre-increment:将$i的值递增到2并输出该值。
    • ($i++)......递减后:输出2当前值,然后将值递增到3
  • 注意:在
  • 分配给类型约束变量方面,有两个与此行为密切相关的错误

    • [在 PS v7.3 中修复] GitHub 问题 #17165
    • [截至 PS v7.3.3 仍然存在] GitHub 问题 #19292

($i++)周边$(...)说明

  • $(...)(子表达式运算符)用于在不直接支持语句的上下文中嵌入一个或多个语句的输出。值得注意的是,您可以使用它将命令输出嵌入到可扩展字符串("..."),即执行字符串插值

    • 请注意,$(...)只需要嵌入表达式(例如,包含在(...)中的东西,属性访问($foo.bar),索引($foo[0])和方法调用($foo.Baz()))和命令(例如,Get-Date),而不是单纯的变量引用,例如在"Honey, I'm $HOME"中。有关 PowerShell 中的可扩展字符串的详细信息,请参阅此答案。
  • 虽然在您的简单示例中不需要扩展字符串 - 只是($i++)会产生看起来相同的输出[1]-$(...)对于使($i++)的值成为较大字符串的一部分很有用;例如,"Iteration #$(($i++))"打印"Iteration #0""Iteration #1"、...


[1]($i++)是一个数字,而"$(($i++)"是一个字符串,其中数字到字符串的转换是字符串插值的一部分。 虽然这通常会导致相同的控制台输出,但对于非整数(如1.2),它实际上可能有所不同,因为直接输出应用区分区域性的字符串化,而字符串插值是文化不变的。因此,实际上使用,作为小数点的区域性 - 例如,fr-FR1.2打印 - 区域性适当 - 作为控制台1,2,而"$(1.2)"始终打印为1.2

在powershell中,赋值也是表达式。 但通常不会显示表达式的输出。 因为函数内的任何输出都会由它返回。

PS C:usersjs> $a = ($b = 1)
PS C:usersjs> $a
1
PS C:usersjs> $b
1    

顺便说一句,$( ) 不仅适用于内部字符串。 您可以在其中放置多个语句,用分号分隔,并使用 foreach 和 if 等关键字,然后将其放在可以放置表达式(管道)的任何位置。

PS C:usersjs> $(if ($true) { echo hi }; echo there) | measure

Count    : 2
Average  :
Sum      :
Maximum  :
Minimum  :
Property :

最新更新