我教自己的Powershell所以我不知道它的一切.
我需要使用我输入的确切行数(数据库是预定义的)搜索数据库,它包含> 11800个条目.
你能帮我找一下这个慢的原因吗?
码:
$Dict = Get-Content "C:\Users\----\Desktop\Powershell Program\US.txt" if($Right -ne "") { $Comb = $Letter + $Right $total = [int]0 $F = "" do { $F = $Dict | Select-Object -Index $total if($F.Length -eq $Num) { if($F.Chars("0") + $F.Chars("1") -eq $Comb) { Add-Content "C:\Users\----\Desktop\Powershell Program\Results.txt" "$F" } } $total++ Write-Host $total } until([int]$total -gt [int]118619) $total = [int]0 $F = "" }
如何逐行搜索/匹配处理加快这一行?我是通过多线程做的吗?如果是这样的话?
看起来你在powershell之前至少已经知道了另一种语言,并且最初基本上复制了你在另一种语言中所做的事情.这是学习一门新语言的好方法,但当然在开始时你最终可能会遇到一些有点奇怪或无法表现的方法.
首先,我想分解您的代码实际执行的操作,作为一个粗略的概述:
一次读取文件的每一行并将其存储在$Dict
变量中.
循环次数与行数相同.
在循环的每次迭代中:
获取与循环迭代匹配的单行(主要通过另一次迭代,而不是索引,稍后再详述).
获取该行的第一个字符,然后获取第二个字符,然后将它们组合起来.
如果它等于预定字符串,请将此行附加到文本文件.
要了解原因,您需要了解PowerShell中的管道.接受和处理管道的Cmdlet会占用一个或多个对象,但它们一次处理一个对象.他们甚至无法访问管道的其余部分.
对于Select-Object
cmdlet 也是如此.因此,当您将一个包含18,500个对象的数组放入其中并将其输入时Select-Object -Index 18000
,您需要发送17,999个对象进行检查/处理,然后才能为您提供所需的对象.您可以看到索引越大,所用时间越长越长.
既然你已经有了一个数组,你可以通过索引用方括号直接访问任何数组成员,[]
如下所示:
$Dict[18000]
对于给定的数组,无论索引是什么,都需要相同的时间.
现在Select-Object -Index
只要一个非常大的索引,你可能不会注意到需要多长时间.问题是你已经在整个数组中循环,所以这很复杂.
你基本上不必做总和1..18000
大约是或大约162,000,000次迭代!(感谢user2460798纠正我的数学)
我测试了这个.首先,我创建了一个包含19,000个对象的数组:
$a = 1..19000 | %{"zzzz~$_"}
然后我测量了两种访问它的方法.首先,用select -index
:
measure-command { 1..19000 | % { $a | select -Index ($_-1 ) } | out-null }
结果:
TotalMinutes : 20.4383861316667 TotalMilliseconds : 1226303.1679
然后使用索引operator([]
):
measure-command { 1..19000 | % { $a[$_-1] } | out-null }
结果:
TotalMinutes : 0.00788774666666667 TotalMilliseconds : 473.2648
结果非常引人注目,使用时间要长近2,600倍Select-Object
.
以上是导致您大幅放缓的唯一因素,但我想指出其他一些事情.
通常在大多数语言中,您将使用for
循环来计数.在PowerShell中,这将是这样的:
for ($i = 0; $i -lt $total ; $i++) { # $i has the value of the iteration }
简而言之,for
循环中有三个语句.第一个是在循环开始之前运行的表达式.$i = 0
将迭代器初始化为0
,这是第一个语句的典型用法.
接下来是有条件的; 这将在每次迭代时进行测试,如果返回true,循环将继续.这里$i -lt $total
比较检查,看$i
是否小于$total
其他地方定义的其他变量的值,可能是最大值.
最后一个语句在循环的每次迭代中执行.$i++
与此相同$i = $i + 1
在这种情况下,我们$i
在每次迭代时递增.
它比使用do
/ until
loop 更简洁,并且更容易理解,因为for
循环的含义是众所周知的.
如果您有兴趣了解更多的反馈工作你写的代码,看看代码审查.在发布之前请仔细阅读那里的规则.