如何比较 dotnet 包和 txt

How to compare dotnet packages and txt

我有脚本:

$Test = (dotnet list C:\Tasks.Api.csproj package) 它提供了一些包(最后有 2 个空格!):

Project 'Tasks.Api' has the following package references 
   [net5.0]:  
   Top-level Package                               Requested   Resolved 
   > AspNetCore.HealthChecks.SqlServer             6.0.0       6.0.0    
   > Microsoft.ApplicationInsights.AspNetCore      2.18.0      2.18.0   
   > Microsoft.EntityFrameworkCore.Tools           5.0.11      5.0.11   
   > Swashbuckle.AspNetCore                        6.2.3       6.2.3
 (SPACE)
 (SPACE)

gettype 提供下一个:

然后我有一个“好的”文件(txt):

AspNetCore.HealthChecks.SqlServer
Microsoft.ApplicationInsights.AspNetCore

现在我想知道,我的“好”文件是否包含来自 $Test 的行?

我想我尝试了数百万种其他选择,但现在我坚持使用它:

$whiteliste = Get-Content C:\whitelist.txt 
$test = (dotnet list C:\Tasks.Api.csproj package) 
$array = @() 
$test[3..($test.Length-2)] | foreach { 
$array+=$_ 
} 
Foreach ($item in $array) { 
Write-host "!!!" $item 
$containsWord = $whiteliste | %{$_ -contains $item.Remove(" ")} 
if ($containsWord -contains $true) { 
    Write-Host "There is!" 
} else { 
    Write-Host "There ins't!" 
} 
} 

谢谢!

不用花哨,一个简单的解决方案是使用 -Match 运算符来查找那些包引用,因为它们是唯一的名称,我们可以利用一些 用户友好的 正则表达式:

$whiteliste = (Get-Content -Path "C:\whitelist.txt").Foreach{[regex]::Escape($_.Trim())} -join "|"
$test.Foreach{
    if ($_ -match $whiteliste) {
        Write-Host -Object "Found: [$($Matches[0])]"
    }
}

编辑根据您对 Santi 的 post 的评论,如果您希望它在没有找到匹配项时告诉您,您可以添加 Begin、Process 和 End 子句:

$test.ForEach{
    Begin { $Matches = $null }
    Process { 
        if ($_ -match $tomatch) { 
            Write-Host -Object "Found: $($Matches[0])" 
        } 
    }
    End { 
        if ($null -eq $Matches) { 
            "No Match Found:(" 
        } 
    }
}
  • 首先,Begin子句会将$matches的自动变量设置为$null这样它就不会干扰过去的比赛
  • 然后,Process 子句将 运行 您的代码添加到 $matches
  • 最后,End 子句将检查 $matches 是否已填充,如果没有,则输出未找到任何内容。
    • 这是可行的,因为 -match 将在找到某些内容时填充 $matches 变量。
    • 如果未找到任何内容,则不会填充变量。

我相信您可以使用 -match for checking this, -contains 将仅适用于数组的 精确匹配

这是一个最小的例子:

$test = dotnet list C:\Tasks.Api.csproj package
$good = Get-Content goodfile.txt

foreach($i in $test) {
    foreach($z in $good) {
        if($i -match $z) {
            "I've got a match!!! [ $i ]"
            # no need to keep comparing, `break` the inner loop
            break 
        }
    }
}

这将导致:

I've got a match!!! [ > AspNetCore.HealthChecks.SqlServer             6.0.0       6.0.0 ]
I've got a match!!! [ > Microsoft.ApplicationInsights.AspNetCore      2.18.0      2.18.0 ]

另一个很好的选择是在他的有用评论中使用 -like and adding wildcards to the RHS of the comparison, as pointed out by shadow2020

if($i -like "*$z*") {
    "I've got a match!!! [ $i ]"
    break
}

根据您的最后一条评论,如果没有匹配项,我们如何添加评论:

:outer foreach($i in $test) {
    # if this line is only white space, skip it
    if([string]::IsNullOrWhiteSpace($i)) {
        continue
    }
    
    foreach($z in $good) {
        if($i -match $z) {
            "I've got a match!!! [ $i ]"
            # no need to keep comparing,
            # `continue` with the next element of the outer loop
            continue outer
        }
    }

    # if we're here, no element of `$good`
    # was matched with all elements of `$test`
    "Couldn't find a match for [ $i ]"
}

结果将是:

Couldn't find a match for [ [net5.0]: ]
Couldn't find a match for [ Top-level Package                               Requested   Resolved ]
I've got a match!!! [ > AspNetCore.HealthChecks.SqlServer             6.0.0       6.0.0 ]
I've got a match!!! [ > Microsoft.ApplicationInsights.AspNetCore      2.18.0      2.18.0 ]
Couldn't find a match for [ > Microsoft.EntityFrameworkCore.Tools           5.0.11      5.0.11 ]
Couldn't find a match for [ > Swashbuckle.AspNetCore                        6.2.3       6.2.3 ]

请参阅 Using a labeled continue in a loop,其中描述并解释了此示例中 continue outer 的用法。