这是一小段代码,以 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-FR
,1.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 :