首页 > 解决方案 > PowerShell - 找到关键字A的第一个条目后查找关键字B的下一个条目

问题描述

我正在寻找使用 Powershell 自动调整文本配置文件中的一些“最大值”值。配置文件看起来像这样(但包含大约 200 个条目)。

ChannelName          = ItemA
Min                  = 0.0
Max                  = 100.0
Units                = Deg C

ChannelName          = ItemB
Units                = Deg C
Min                  = 0.0
OtherItem1           = 123
OtherItem2           = 456

ChannelName          = ItemC
Units                = Deg C
Min                  = 0.0
Max                  = 100.0

应当指出的是,

我很感激我没有包含一些适当的示例代码,但作为一个新手,我什么都做不了,因此寻求帮助。我希望代码按如下方式工作,

示例任务:将“ItemB”的“Max”值设置为 200

Get-Content "C:\ConfigFile.txt"
Scan down text file looking for 'ItemB'
Error message if Item B not found and exit
If ItemB is found, continue down the list until either 'ChannelName' or 'Max' is found
If a 'ChannelName' entry is found first, 'ItemB' is missing its 'Max' entry - Error message and exit
If a 'Max' entry is found first, set 'Max' to equal 200

我们需要确保进行适当的错误检查,以确保 ItemC 的“Max”值不会因为本示例中缺少 ItemB 的“Max”值而错误地更改为 200。

标签: powershelltextmatching

解决方案


这是一种方法。

将文件作为单行多行字符串读取并在空换行符上拆分以获取“通道”文本块数组。

循环遍历块,如果块用于通道“ItemB”,请检查是否有最大值。如果没有,请将其添加到块中。

最后,再次用两个换行符加入文本块并写入文件

$channelNameToUpdate = 'ItemB'  # or 'Speed' or 'SpeedAverage' or..
# split on two (or more) newlines and discard any block that is empty or whitespace-only
$data = (Get-Content -Path 'D:\Test\theconfigfile.txt' -Raw) -split '(\r?\n){2,}' | Where-Object {$_ -match '\S'}
for ($i = 0; $i -lt $data.Count; $i++) {
    if ($data[$i] -match "(?m)^ChannelName\s+=\s*$channelNameToUpdate\s*$") {
        if ($data[$i] -notmatch '(?m)^Max') {
            # no Max.. line, so add it
            $data[$i] += "`r`nMax                  = 200.0"
        }
        else {
            # replace the existing Max.. line
            $data[$i] = $data[$i] -replace '(?m)^Max.*$', "Max                  = 200.0"
        }
    }
}

# join the textblocks with a double newline and overwrite the original file
# -PassThru will show the result on screen
$data -join "`r`n`r`n" | Set-Content -Path 'D:\Test\theconfigfile2.txt' -PassThru -Force

输出:

ChannelName          = ItemA
Min                  = 0.0
Max                  = 100.0
Units                = Deg C

ChannelName          = ItemB
Units                = Deg C
Min                  = 0.0
OtherItem1           = 123
OtherItem2           = 456
Max                  = 200.0

ChannelName          = ItemC
Units                = Deg C
Min                  = 0.0
Max                  = 100.0

如果要在文件中缺少的任何地方添加 Max 值,只需将 for 循环更改为

for ($i = 0; $i -lt $data.Count; $i++) {
    if ($data[$i] -notmatch '(?m)^Max') {
        $data[$i] += "`r`nMax                  = 200.0"
    }
}

正则表达式详细信息:

(?m)^ChannelName\s+=\s ItemB\s $

(?m)            Match the remainder of the regex with the options: ^ and $ match at line breaks (m)
^               Assert position at the beginning of a line (at beginning of the string or after a line break character)
ChannelName     Match the characters “ChannelName” literally
\s              Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   +            Between one and unlimited times, as many times as possible, giving back as needed (greedy)
=               Match the character “=” literally
\s              Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   *            Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
ItemB           Match the characters “ItemB” literally
\s              Match a single character that is a “whitespace character” (spaces, tabs, line breaks, etc.)
   *            Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
$               Assert position at the end of a line (at the end of the string or before a line break character)

(?m)^最大

(?m)           Match the remainder of the regex with the options: ^ and $ match at line breaks (m)
^              Assert position at the beginning of a line (at beginning of the string or after a line break character)
Max            Match the characters “Max” literally

推荐阅读