【问题标题】:Powershell: unexpected behavior of negated -like and -match conditionalsPowershell:否定 -like 和 -match 条件的意外行为
【发布时间】:2017-12-23 13:32:36
【问题描述】:

我的 windows 文件夹中有 2 个文件夹,分别是 software 和 softwaretest。 所以我有主文件夹“软件”if语句,然后跳转到elseif - 这里我有备份文件夹,所以跳转到else...

我的问题是我从 elseif 获取写入主机,并且我有一个备份文件夹,我正在调用 softwaretest,所以不明白为什么它给我输出而不是 else。

希望有人可以指导/帮助我:-)

    If ($SoftwarePathBackup = Get-ChildItem -Path "$Env:SystemRoot" | Where-Object { (!$_.Name -like 'software') }) {
        Write-Host ( 'There are no folder named \software\ on this machine - You cant clean/clear/empty the folder!' ) -ForegroundColor Red;
    } elseif ($SoftwarePathBackup = Get-ChildItem -Path "$Env:SystemRoot" | Where-Object { ($_.Name -match '.+software$|^software.+') } | Sort-Object) {
        Write-Host ( 'There are none folder-backups of \software\ on this machine - You need to make a folder-backup of \software\ before you can clean/clear/empty the folder!' ) -ForegroundColor Red;
    } else {
        Remove-Item
    }

【问题讨论】:

  • 你使用$_.Name -match '.+software$|^software.+'而不是$_.Name -like 'softwaretest'的原因是什么?
  • 嗨 Paxz.. 我和常规 exp./RegEX。 :-) 最后一个表达式将为软件返回 true,对吗?它不适用于备份软件和软件备份,对吗? - elseif 语句需要查看名称中包含软件的文件夹,但不是独立单词软件,如果没有名称包括软件.. 然后运行 ​​elseif - 然后“软件”之前和之后的单词/字母可以任何单词/字母,softwaretest 只是一个例子。

标签: regex powershell if-statement wildcard negation


【解决方案1】:

我觉得在右边或什至在 RegEx 中都有否定非常令人困惑。我认为用!-not 一开始就否定会更明显。

要测试,如果一个文件夹存在,你可以使用Test-PathTest-Path 也有一个-Filter 参数,您可以使用它来代替Where-Object。但我认为你甚至不必过滤。

$SoftwarePath = "$($Env:SystemRoot)\Software", "$($Env:SystemRoot)\SoftwareBackup"

foreach ($Path in $SoftwarePath) {
    if (Test-Path -Path $Path) {
        Remove-Item -Path $Path -Force -Verbose
    }
    else {
        Write-Output "$Path not found."
    }
}   

这对你有用吗?

【讨论】:

  • 可以工作,但 SoftwareBackup 只是一个名称,它可以是其他任何名称,例如 software 或 ^software* 或 *software$。唯一的作用就是不能是^software$
【解决方案2】:

您的主要问题运算符优先级之一:

  • !$_.Name -like 'software' 应该是 ! ($_.Name -like 'software') 或者最好是
    $_.Name -notlike 'software' - 使用 PowerShell 的 not 前缀运算符进行否定。

  • 同样,您可能想要否定 $_.Name -match '.+software$|^software.+',这很容易通过$_.Name -notmatch '.+software$|^software.+' 实现

正如Get-Help about_Operator_Precedence 中所述,!(又名-not)的优先级高于-like,因此!$_.Name -like 'software' 被评估为(!$_.Name) -like 'software',这意味着结果!$_.Name - 一个 Boolean - 与通配符模式 'software' 比较(字符串),它总是 返回 $False,所以 If 分支永远不会输入。


也就是说,您可以完全不使用-like-match,并使用Get-Item-Include 参数支持的隐式通配符匹配(sn-p 需要PSv3+):

# Get folders whose name either starts with or ends with 'software', including
# just 'software' itself.
$folders = Get-Item -Path $env:SystemRoot\* -Include 'software*', '*software' | 
             Where-Object PSIsContainer

# See if a folder named exactly 'software' is among the matches.
$haveOriginal = $folders.Name -contains 'software'

# See if there are backup folders among the matches (too).
# Note that [int] $haveOriginal evaluates to 1 if $haveOriginal is $True,
# and to 0 otherwise.
$haveBackups = ($folders.Count - [int] $haveOriginal) -gt 0

# Now act on $folders as desired, based on flags $haveOriginal and $haveBackups.
  • 注意Get-Item -Path $env:SystemRoot\* 是如何用于显式预选所有项的(如果隐藏项也应该包含,则添加-Force),然后过滤通过-Include

  • 由于Get-Item - 不像Get-ChildItem- 不支持-Directory,所以| Where-Object PSIsContainer 用于进一步限制对目录(文件夹)的匹配。

  • 1234563亦指明;虽然-Recurse 可以与-Depth 0 (PSv3+) 结合使用以限制匹配直接子目录,Get-ChildItem 显然仍试图读取 allentries子目录也是如此,这可能会导致来自甚至不感兴趣的目录的不需要的访问被拒绝错误。
    换句话说:Get-ChildItem -Recurse -Depth 0 -Directory $env:SystemRoot -include 'software*', '*software' 仅在您(至少)拥有对$env:SystemRoot所有子目录的读取权限时才等效。

【讨论】:

  • 嗨 mklement0 - 这是有效的,给我正确的文件夹值 TRUE/FALSE,所以我将为该代码构建一个 IF 语句,所以我得到了 if、elseif 和 else .然后为 CSC 和 System32 文件夹的 $folders 添加 -exclude,因为我的访问被拒绝了......祝你圣诞快乐。 ...但可以看到我无法为与 -Include 相同的代码行添加 -Exclude。
  • 很高兴听到这个消息。至于-Exclude:一般来说,你应该可以把-Include-Exclude结合起来。
  • 是的,已经尝试过 $excludewildcard = 'csc', 'system32' - 但我仍然拒绝访问这两个文件夹...
  • 我明白了:在应用-Exclude 时,拒绝访问错误已经发生。请查看我的更新,它现在使用Get-Item 而不是Get-ChildItem 来防止这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
  • 2012-12-14
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 2012-02-12
相关资源
最近更新 更多