循环范围与步长

10
我正在尝试从BATCH转向PowerShell,并且正在尝试转换我的自己的脚本。
我的问题出在循环中的范围:我的原始BATCH脚本是这样的。
   for /L %%U in (123,2,323) do ECHO %%U

并且会打印
123
125
127
...

使用Powershell,一个范围可以是123..323,因此
123..323 | % {Echo $_ }

会给我吗?
123
124
125
...

有没有办法设置一个步长不等于1的范围?我找到的所有示例要么列出所有的数字(我有几百个...),要么使用数字之间的两个点。

https://dev59.com/s5Hea4cB1Zd3GeqPomfL - si618
谢谢,我在搜索时找不到这个例子,现在我会测试所有建议。 - Lila
3个回答

13

简单的谷歌搜索应该可以帮您找到这个。

for ($i=123; $i -le 323; $i=$i+2 ) {Write-Host $i;}

(初始化;保持循环运行的条件;迭代)


谢谢,我怀疑之前没找到这个解决方案是因为我搜索的关键词不对。现在我会学习如何将变量传递下去。 - Lila
2
@Squashman,你也可以使用+=2,(类似于cmd.exe中的Set /A i+=2),例如For ($i=123; $i -LE 323; $i+=2) {$i} - Compo
@Squashman 这个解决方案让我对步骤有了所需的控制(而且很容易理解,因为它就像 PHP 中的计数器),我成功地转换了我的一些现有批处理脚本。PowerShell 脚本证明是 2 倍更快的,所以这对我的脚本编写是一个必要的改进! - Lila
@Lila Powershell确实可以用比批处理文件更少的代码完成许多任务,但仍有很多事情批处理文件可以比PowerShell更有效地完成。我可以在批处理文件中编写10倍于Powershell一行代码的代码行数,但运行速度却更快。 - Squashman
实际上,是谷歌把我带到这里的。感谢您为SO文档做出的贡献。 - Chris Hayes

4

使用原始方法(步骤2):

(123..323) | % {if( $_ -band 1 ) {$_ }}

第三步及更高步骤:

 (123..323) | % {if( !($i++ % 3) ) {$_ }} 

我几乎看不到迭代从起始值到结束值并设定步长的循环与您的方法有相似之处,尽管它们有同样的效果。 - user6811411
好的,在这种情况下 (123..323) | % {if( !($i++ % 3) ) {$_ }} 更好,但我喜欢使用快速二进制运算符的方法。 - f6a4
我不太明白如何将步长从2更改为另一个给定的数字。 - Lila
请看上面的注释。 - f6a4

0
一个更简洁的方法来创建一个步长为n的范围,假设变量$n包含步长值,可以这样写:
1..25 | ? { !($_ % $n) } 
?Where-Object 命令的别名。而 $_ % $n 可以更明确地写为 $_ % $n -eq 0,因此上述内容也可以写成:
1..25 | Where-Object { $_ % $n -eq 0 }

Where-Object作为一个过滤器,只包括与步长取模等于0的值:$_ % $n -eq 0。 之所以可以写成!($_ % $n)是因为PowerShell将0视为false,其他数字视为true。因此,用!0取反使其评估为true,然后导致该数字被包括在范围内。

因此,对于步长为2,您可以这样写:

123..323 | ? { !($_ % 2) }  

这包括仅为偶数的数字(124、126、...)。 要仅包括奇数(从123开始),一个简单的技巧是:
123..323 | ? { $_ % 2 }

当模数计算结果为1时,这种情况发生在奇数,它被包括在最终的范围内。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接