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

fbcarpbf  于 2023-01-20  发布在  Shell
关注(0)|答案(2)|浏览(183)

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

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

这怎么可能呢?

mwkjh3gx

mwkjh3gx1#

评论中有很好的指针,但让我再深入一点:

    • 关于$i++的解释**:
      • $i++使用增量运算符++将变量$i的值增加1**,这在诸如C#和C/C ++之类的语言中可能是熟悉的。如预期的,还存在互补的 * 减量 * 运算符--
  • 由于++位于变量的 * 之后 *(*后缀 * 形式),因此递增发生在变量值在语句中使用 * 之后 *。

将它放在变量-++$i前缀 * 形式 之前 * 将执行递增 * first *。
如果单独使用递增/递减操作,则该区别是无关紧要的。

  • 假定$i包含 * numeric * 类型的示例,否则将出错;如果变量$i尚未初始化,则其值实际上为$null,PowerShell将其强制为[int]类型的0。因此,$i++在其语句的上下文中计算为0,之后递增为1
  • $i++这样的递增/递减表达式被视为 * 赋值*-您可以将其视为$i = $i + 1-并且PowerShell * 中的赋值不产生输出*(它们不返回任何内容;它们仅更新变量的值)。
    • 关于$i++周围(...)的解释**:
      • 通过将一个 * 赋值语句 * 括在括号((...)中,您可以将其转换为一个 * 表达式 *,这意味着赋值语句的 * 值 * 通过***传递,以便它可以参与一个更大的表达式;例如:
  • $i = 0 ...无输出-仅将值0赋给变量$i
  • ($i = 1) ...输出1:由于(...),也输出指定值。
  • (++$i) ...增量前:将$i的值递增到2并输出该值。
  • ($i++) ...递减后:输出当前值2,* 然后 * 将该值递增至3
    • 关于($i++)$(...)的解释**:
      • $(...)是子表达式运算符**,用于在语句不直接受支持的上下文中嵌入一个甚至多个语句的输出。特别是,您可以**使用它将命令输出嵌入 * 可扩展字符串 "..."),即执行 * 字符串插值
  • 请注意,只有嵌入 * 表达式 * 时才需要$(...)(例如,包含在(...)中的内容,属性访问($foo.bar),索引,($foo[0])和方法调用($foo.Baz()))和 * 命令 *(例如Get-Date),而不仅仅是"Honey, I'm $HOME"中的变量引用。有关PowerShell中可扩展字符串的详细信息,请参阅this answer
  • 虽然在您的简单示例中并不严格需要可扩展字符串-仅($i++)将生成看起来相同的输出[1]-但$(...)对于使($i++)的值成为更大字符串的一部分非常有用;例如,"Iteration #$(($i++))"可打印"Iteration #0""Iteration #1" ...

[1]($i++)是 * number *,而"$(($i++)"是 * string *,其中数字到字符串的转换是作为字符串插值的一部分进行的。虽然 * 通常 * 会产生相同的控制台输出,但对于 * 非整数 * 数字(如1.2),它实际上可能会有所不同,因为直接输出应用了 * 区分区域性 * 的字符串化,而字符串插值是区域性 * 不变 * 的。因此,对于使用,作为小数点的有效区域性(例如fr-FR),1.2将在区域性方面适当地作为1,2打印到控制台,而"$(1.2)" * 始终 * 打印为1.2

w41d8nur

w41d8nur2#

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

PS C:\users\js> $a = ($b = 1)
PS C:\users\js> $a
1
PS C:\users\js> $b
1

顺便说一句,$()并不仅仅适用于字符串内部,你可以在里面放多个语句,用分号隔开,使用foreach和if这样的关键字,然后把它放在任何你能放表达式的地方(管道)。

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

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

相关问题