在 Powershell 中过滤具有多个条件的 Foreach-Object 结果不起作用

filter Foreach-Object results with multiple conditions in Powershell not working

我正在尝试使用 Powershell 7 过滤 git 中已更改文件的列表。我只想要以 'packages' 或 'database' 开头的文件路径。当我 运行 代码时,结果没有被过滤,所有的东西都被返回了。我怎样才能让过滤工作?我是 Powershell 脚本的新手。

这是我的代码:

$editedFiles = git diff HEAD [git commit id] --name-only
$editedFiles | ForEach-Object {
    $sepIndex = $_.IndexOf('/')
    if($sepIndex -gt 0 -and ($_ -contains 'packages' -or 'database')) {
        Write-Output $_      
    }
}

这里有两点需要注意:

-contains 是一个 集合包含运算符 - 对于字符串,您需要 -like 通配符比较运算符:

$_ -like "*packages*"

-match 正则表达式运算符:

$_ -match 'package'

这里要注意的另一件事是 -or 运算符 - 它只需要 布尔值 操作数 ($true/$false) ,如果你传递任何其他东西,它会 convert 操作数到 [bool] 如有必要。

也就是说下面这种语句:

$(<# any expression, really #>) -or 'non-empty string'

ALWAYS returns $true - 因为非空字符串在转换为 [bool].

时计算结果为 $true

相反,您需要更改两个单独的比较:

$_ -like '*packages*' -or $_ -like '*database*'

或者,您可以使用 -match 运算符 一次,方法是使用交替 (|):

$_ -match 'package|database'

最后得到类似的东西:

$editedFiles | ForEach-Object {
    $sepIndex = $_.IndexOf('/')
    if($sepIndex -gt 0 -and $_ -match 'package|database') {
        Write-Output $_      
    }
}

如果过滤是您打算在 ForEach-Object 块中执行的所有操作,您不妨使用 Where-Object - 它的设计 正是 为此 :)

$editedFiles | Where-Object {
    $_.IndexOf('/') -gt 0 -and $_ -match 'package|database'
}