首页 > 解决方案 > 如何使用 Powershell 循环检查匹配字符串?

问题描述

我有一个 INI 文件。我想将字符串与 INI 文件中的节点匹配。我想循环检查字符串。我试过这个,但我发现一个问题,当它不匹配时,它会循环,但是当我用我想要匹配的字符串修改INI文件匹配时,它仍然循环并且不能为结果返回true。这是 INI 文件的样子

[State]
downloadstage=123

function CPTGM {
    Write-Host "Capturing"
}

function Check_Stage {
    $INI_Path = "D:\FILE.ini"
    $INI_File = @{}
    Get-Content $INI_Path | ForEach-Object {
        $_.Trim()
    } | Where-Object {
        $_ -notmatch '^(;|$)'
    } | ForEach-Object {
        if ($_ -match '^\[.*\]$') {
            $section = $_ -replace '\[|\]'
            $INI_File[$section] = @{}
        } else {
            $key, $value = $_ -split '\s*=\s*', 2
            $INI_File[$section][$key] = $value
        }
    }
    $String = "123"
    $n = 0
    while (-not ($INI_File["State"]["downloadstage"] -eq "$String")) {
        Start-Sleep -s 1
        $n++
        Write-Host "Attempt no $n"
    }

    Write-Host ">>String found after $n attempts"
    Write-Output "Continue to Capture"
    CPTGM
}

Check_Stage

标签: powershell

解决方案


问题是您只读取一次 *.ini 文件,并在while循环的每次迭代中测试相同的固定内容。如果第一次出现搜索字符串,它将立即退出 while 循环,但如果第一次不出现,它将永远不会再次读取文件以查看它是否已更改。

您需要在 while 循环中移动“读取 ini 文件”代码,以便$INI_File每次刷新并获取外部程序所做的任何更改。

此外,您可以使用 devblogs.microsoft.com 中的此函数解析 ini 文件,然后查询结构化结果,而不是自己抓取 ini 文件。

https://devblogs.microsoft.com/scripting/use-powershell-to-work-with-any-ini-file/

function Get-IniContent ($filePath)
{
    $ini = @{}
    switch -regex -file $FilePath
    {
        “^\[(.+)\]” # Section
        {
            $section = $matches[1]
            $ini[$section] = @{}
            $CommentCount = 0
        }
        “^(;.*)$” # Comment
        {
            $value = $matches[1]
            $CommentCount = $CommentCount + 1
            $name = “Comment” + $CommentCount
            $ini[$section][$name] = $value
        } 
        “(.+?)\s*=(.*)” # Key
        {
            $name,$value = $matches[1..2]
            $ini[$section][$name] = $value
        }
    }
    return $ini
}

你的Check_Stage然后变成这样:

function Check_Stage {
    $INI_Path = "D:\FILE.ini"
    $INI_File = Get-IniContent $INI_Path # use Get-IniContent rather than your own version
    $String = "123"
    $n = 0
    while (-not ($INI_File.State.downloadstage -eq $String)) {
        Start-Sleep -s 1
        $n++
        Write-Host "Attempt no $n"
        $INI_File = Get-IniContent $INI_Path # read the ini file again to pick up any changes
    }

    Write-Host ">>String found after $n attempts"
    Write-Output "Continue to Capture"
    CPTGM
}

推荐阅读