使用powershell,我试图确定目录中哪些perl脚本没有从任何其他脚本中调用。在Select中,我对匹配进行分组,因为我使用了一些其他逻辑来筛选出注释行的结果,以及一些我想排除的其他场景(为了简单起见,我从下面发布的代码中排除了这一点)。我的主要问题是"-notin“部分。
如果我从string中移除分组,并且只匹配文件名本身,我就可以让它工作。所以这是可行的。
$searchlocation = "C:\Temp\"
$allresults = Select-String -Path "$searchlocation*.pl" -Pattern '\w+\.pl'
$allperlfiles = Get-Childitem -Path "$searchlocation*.pl"
$allperlfiles | foreach-object -process{
$_ | where {$_.name -notin $allresults.matches.value} | Select -expandproperty name | Write-Host
}然而,我不能让下面的工作。这与上面的唯一区别是"-Pattern“的值和"-notin”之后的值。我不知道如何与匹配的组一起使用"notin“。
$searchlocation = "C:\Temp\"
$allresults = Select-String -Path "$searchlocation*.pl" -Pattern '(.*?)(\w+\.pl)'
$allperlfiles = Get-Childitem -Path "$searchlocation*.pl"
$allperlfiles | foreach-object -process{
$_ | where {$_.name -notin $allresults.matches.groups[2].value} | Select -expandproperty name | Write-Host}在较高级别上,代码应该搜索目录中的所有perl脚本,查找执行任何其他perl脚本的任何行。现在我有了$allresults,它基本上给出了从其他文件调用的所有perl脚本的列表。为了得到相反的结果(没有从任何其他文件调用的文件),我会得到目录中所有perl脚本的列表,循环这些脚本,并列出那些在$allresults中没有出现的脚本。
发布于 2019-07-29 20:10:27
当您选择一个分组时,您的需要使用Select语句,或者在循环中迭代,否则您将只选择Nth匹配中的值。
如果您的$Allresults对象包含
File.pl,文件2.pl,文件3.pl
然后$allresults.Matches.Groups[2].value 只返回 File2.pl
相反,您需要选择这些值!
$allresults | select @{N="Match";E={ $($_.Matches.Groups[2].value) } }将返回的:
Match
-----
File1.pl
File2.pl
File3.pl在您的具体示例中,每个匹配都有三个子项,结果将是完全连续的,所以您将“匹配1,组1”称为groups[0],而“匹配2,组1”是groups[3]。
这意味着您所关心的匹配(具有分组2的匹配)在集合{2,5,8,11,……}中包含的数组值中,或者可以描述为(N*3-1),其中N是匹配的数目。因此,对于Match 1 = (1*3)-1 = [2];而对于Match 13 = (13*3)-1 = [38]
您可以使用循环来遍历它们以检查:
for($i=0; $i -le ($allresults.Matches.groups.count-1); $i++){
"Group[$i] = ""$($allresults.Matches.Groups[$i].value)"""
}我注意到,在收集数据时,您花了一些时间避免循环,但在匹配数据时,似乎意外地成为使用循环的牺牲品。
Not-In和其他比较,当select和where子句使用时,不需要循环结构,如果不循环,则更快,因此您可以放弃Foreach-object循环,只使用简单的Where (?)就可以得到更好的处理。
$SearchLocation = "C:\Temp\"
$FileGlob = "*.pl"
$allresults = Select-String -Path "$SearchLocation$FileGlob" -Pattern '(.*?)([\w\.]+\.bat)'
$allperlfiles = Get-Childitem -Path "$SearchLocation$FileGlob"
$allperlfiles | ? {
$_.name -notin $(
$allresults | select @{N="Match";E={ $($_.Matches.Groups[2].value) } }
)
} | Select -expandproperty name | Write-Host现在,应该是更快的和更简单的代码来维护,但是,正如您可能已经注意到的,由于没有循环,仍然有一些冗余。
当您将所有的内容都编成一个Select,它可以完成where的工作,而且更重要的是,您只需要匹配这里的NAME属性,这样您就可以选择最后一个选择,首先只选择文件的名称,或者您可以放弃where并选择您想要的内容。
我认为前者要简单得多,而后者是有用的,如果您要对循环中的其他值做一些我们还不知道的事情。
最后,写主机可能是多余的,因为任何对象输出都会回显到控制台。
这里是一个版本,它包含了删除不必要的循环和删除与您想要的信息的输出相关的冗余,所有这些都在一起。
$SearchLocation = "C:\Temp\"
$FileGlob = "*.pl"
$allresults = Select-String -Path "$SearchLocation$FileGlob" -Pattern ('(.*?)([\w\.]+\'+$FileGlob+')')
$allperlfiles = Get-Childitem -Path "$SearchLocation$FileGlob"
$allperlfiles.name | ? {
$_ -notin $(
$allresults | select @{
N="Match";E={
$($_.Matches.Groups[2].value)
}
}
)
}https://stackoverflow.com/questions/57259716
复制相似问题