乐趣区

关于powershell:奇怪的-Powershell

本文用来收集一些应用 Powershell 的时候的一些奇奇怪怪的体验。

0x00 :: 生存还是覆灭?

在操作 汇合 (比方 数组 链表 哈希映射表 等)的时候,有一种叫 算子 的概念。
在 Scala 里它实质上是一些对象的办法,一些语言里它被叫做「高级函数」。

这里次要须要先晓得这俩:

  • map : 对 汇合 里的每一个 元素 ,都指定一个 计算的逻辑 ,该 算子 能够 返回一个新的 汇合 ,外面每个 元素 都是上一个汇合每个 元素 通过该逻辑 后的值。

    • 比方:{2,3,3} 这个汇合,通过 map(你们每个都乘以 3) 解决后,就能返回 {6,9,9} 这样的汇合。
  • flatten : 把一个 汇合 里,若有的 元素 也是 汇合 ,那么该 算子 会返回一个 突破一层外面汇合 的新汇合。

    • 比方:{{1,2},7,{2,3,3},{2,{6,6,6},12},4} 这个汇合,通过 flatten 解决后,返回的汇合就是 {1,2,7,2,3,3,2,{6,6,6},12,4} 这样的。
  • flatmap : 其实,flatmap(xxx) 就等同于先 map(xxx) 而后 flatten

    • 比方:
      如果,汇合乘法成果是这样:{1,2,3} * 2 => {1,2,3,1,2,3}
      那么,{{1,2},7,{{2,3,3}}} 通过 flatmap(每个元素给我乘 2) 后,就等于先被变成 {{1,2,1,2},14,{{2,3,3},{2,3,3}}} 这样,再变成 {1,2,1,2,14,{2,3,3},{2,3,3}} 这样。

      这其实就如同,你有一个小破船,船上运者一些货物,有的货是一般货、有的货也是小破船,就叫小小破船好了。当初,小破船被鱼雷击中了,这除了导致外面的货物同样被平稳了一下以外,那些小小破船都被平稳侧漏了。小小破船上的货物就都漏了进去,从而它们不再在小小破船上了、而是漏到了小破船上,乌七八糟地、平铺地,摊在那里。

  • foreach : 在 Scala 里的话这个其实就是无返回(即返回 Unit 示意返回空)的 map。个别是要用每个元素做同样一件有 副作用 的事。(比方打印)(这里只有信息不只通过返回传出 or 信息不只通过参数进入函数就都算有副作用)

下面的 flatmap 是前两者的组合而 foreach 可了解为 非凡的 map 那么下面确实只是说了俩 算子,没错。

而本局部要说的,就是 Powershell 的 foreach 仿佛有着相似于 flatmap 的作用这件事了。

就是说,「外面的货色」,存在还是覆灭?要不要击破小小破船、以使其侧漏?

示例

先简略测试,再演示一个略微简单的例子进一步验证。

0.0

1,2,(1,2,3) | foreach {$_ * 3}

应有输入:

3
6
1
2
3
1
2
3
1
2
3

能够看到其中的 (1,2,3) 被反复了三次而没有数值三倍

0.1

1,2,(1,2,3) | foreach {$_ * 3} | foreach {$_ * 7}

应有输入:

21
42
7
14
21
7
14
21
7
14
21

能够看到上一步的后果的 汇合 里其实就曾经是 平坦 的了,那个 (1,2,3) 在乘以三的时候还是一个 汇合 ,但乘以三完了当前也一并被侧漏了开来,在乘以七的时候,就是漏出来的每个元素像后面两个元素一样都被作为外层 汇合 直属元素 来看待了。

1.0

1,2,,(1,2,3) | foreach {$_ * 3} | foreach {$_ * 7}

这里给结尾代码断下句:两个逗号 ,, 并不是一个整体,像 1,2 的逗号作用就像 1+2+ 一样是一个运算符,二元的,相当于一个两参数的函数,只不过,算式 1,2 的返回后果是个元素为 12 的数组;而 ,2 其实也能够类比着 +2 来了解,也是运算符,一元运算符,只不过 ,2 的返回还是个数组,一个单元素的数组。

所以,不难理解,这里的 ,(1,2,3) 才是一个整体,手动明确一下运算符的优先级的话,结尾那块儿的 1,2,,(1,2,3) 就应该是这样写了:1,2,(,(1,2,3))

它应有这样的输入:

21
42
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3
1
2
3

能够看见这回外面的 (1,2,3) 没有轻易侧漏。但真的是这样吗?

1,2,,(1,2,3) | foreach {$_ * 3} | foreach {$_ * 7} | foreach {$_ * 2}

看看输入:

42
84
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6
2
4
6

1.1

能够看到,其实通过两层 flatten 后,外面的 数字元素们 都曾经平铺到了里面,再到第三层的逻辑为 让所有元素乘以二 的转化操作的后果,就是都被作为数字来操作了。

就如同是,小破船上的小小破船,在平稳后终于上完了厕所,而后永远地来到了这个它们本来所在的小破船。

总结

可见,在 Powershell 里,foreach 其实和 flatmap 有相似的逻辑,或者说二者就是一样的。

其实它确切的名字是 ForEach-Object,而 foreach 则是别名,而且它还有个更短的别名:%
(这部分的常识起源:https://www.jb51.net/article/115518.htm

而它为何会成为 flatmap,或者就能够讲另一个故事了吧。我集体的猜想是这是 Powershell 上的一个个性(都这么久了应该不是 BUG 了吧),即在被返回时会主动拆一次。你能够试试 1,2,(1,2,3)1,2,,(1,2,3) 比照一下并看看后者的提醒。

之所以同 flatmap 分割起来是因为看了这些:

  • https://stackoverflow.com/questions/10442333/what-is-the-powershell-equivalent-to-linqs-select
  • https://stackoverflow.com/questions/5241441/powershell-equivalent-of-linq-selectmany-method
  • https://insbex.jixun.moe/linq-in-pwsh
  • https://or1ko.hatenablog.com/entry/20100125/1264425759

外面有很不错的例子。第四个链接提到了 Map,并指出它相似于 Linux 上的 Awk。
不过并没提及 FlatMap。不过,如果元素确保不会有 汇合,那么 % 的体现确实等同于 map 算子了。

而之所以能把 flatmapforeach 分割起来,还是因为前两个链接里有的答复举的例子,特地是第一个链接里,间接问了这方面的事件。

xxx

退出移动版