PowerShell - 在找到 keywordS 的第一个条目后查找 KeywordS 的下一个条目
PowerShell - Find next entry of KeywordB after finding first entry of keywordA
我希望使用 Powershell 自动调整文本配置文件中的某些 'Max' 值。配置文件看起来像这样(但包含大约 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
需要注意的是,
- 虽然所有 ChannelNames 应该 每个都有一个关联的 'Max' 条目,但如果人们过去错误地手动编辑了这个文件,有些可能不会
- 'Max' 条目并不总是在频道名称后的相同位置,因此我们无法在找到我们感兴趣的频道名称后倒数 X 行
我很感激我没有包含一些正确的示例代码,但作为一个新手,我无法使用任何东西,因此寻求帮助。我希望代码按如下方式工作,
示例任务: 将 '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' 值不会错误地更改为 200,因为此示例中缺少 ItemB 的 'Max' 值。
这是一种方法。
以单行多行字符串形式读取文件,并在空换行符上拆分以获得 'Channel' 个文本块的数组。
循环块,如果块用于通道'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
如果你想在文件中缺少的地方添加一个最大值,只需将 for 循环更改为
for ($i = 0; $i -lt $data.Count; $i++) {
if ($data[$i] -notmatch '(?m)^Max') {
$data[$i] += "`r`nMax = 200.0"
}
}
正则表达式详细信息:
(?m)^ChannelName\s+=\sItemB\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
我希望使用 Powershell 自动调整文本配置文件中的某些 'Max' 值。配置文件看起来像这样(但包含大约 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
需要注意的是,
- 虽然所有 ChannelNames 应该 每个都有一个关联的 'Max' 条目,但如果人们过去错误地手动编辑了这个文件,有些可能不会
- 'Max' 条目并不总是在频道名称后的相同位置,因此我们无法在找到我们感兴趣的频道名称后倒数 X 行
我很感激我没有包含一些正确的示例代码,但作为一个新手,我无法使用任何东西,因此寻求帮助。我希望代码按如下方式工作,
示例任务: 将 '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' 值不会错误地更改为 200,因为此示例中缺少 ItemB 的 'Max' 值。
这是一种方法。
以单行多行字符串形式读取文件,并在空换行符上拆分以获得 'Channel' 个文本块的数组。
循环块,如果块用于通道'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
如果你想在文件中缺少的地方添加一个最大值,只需将 for 循环更改为
for ($i = 0; $i -lt $data.Count; $i++) {
if ($data[$i] -notmatch '(?m)^Max') {
$data[$i] += "`r`nMax = 200.0"
}
}
正则表达式详细信息:
(?m)^ChannelName\s+=\sItemB\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