在配置文件powershell或批处理文件中查找并替换



假设我有一个配置文件,如下所示:

{name1}
Settinga=1
settingb=2
settingc=3
{name2}
Settinga=1
settingb=2
settingc=3
{name3}
Settinga=1
settingb=2
settingc=3

我希望能够将{name3}下的行设置b=2更改为另一个值,如设置b=4

它将是Windows操作系统上的文件存储,因此理想情况下,它将在PowerShell或批处理命令下完成。

有人有什么想法吗?或者这是否可能?

感谢

您可以使用Get-Content读取配置文件,并将每个名称下的部分内容存储在嵌套哈希表中,其中名称行是外部键,设置行被拆分为内部哈希表的键和值。为了维护从原始文件中找到的密钥的顺序,我们可以使用System.Collections.Specialized.OrderedDictionary。要创建一个,只需将[ordered]属性添加到哈希表@{}中即可。您可以在about_Hash_Tables了解更多信息。

我们还可以使用System.String.Split通过=分割行,CCD_7将使用长度来确定行是名称还是设置。长度为1是一个名称,长度为2是一个设置。

# Read lines from config file
$config = Get-Content -Path .config.txt
# Use an ordered hashtable to remember order of keys inserted
$sections = [ordered]@{}
# Keep a key which indicates the current name being added
$currentKey = $null
# Go through each line in the config file
foreach ($line in $config) {
# Split each line by '='
$items = $line.Split("=")
# If splitted items is only one value, we found a new name
# Set the new name and create an inner settings dictionary
if ($items.Length -eq 1) {
$currentKey = $line
$sections[$currentKey] = [ordered]@{}
}
# Otherwise we found a normal line
else {
# Only add the setting if the current name is not null
if ($null -ne $currentKey) {
$sections[$currentKey][$items[0]] = $items[1]
}
}
}

它将给出一个哈希表$sections,如下所示:

Name                           Value
----                           -----
{name1}                        {Settinga, settingb, settingc}
{name2}                        {Settinga, settingb, settingc}
{name3}                        {Settinga, settingb, settingc}

然后你可以设置一个值(或多个值(,如下所示:

$sections["{name3}"].settingb = 4

并使用Out-File将更新后的哈希表写入输出文件。要迭代外部和内部哈希表,我们需要使用System.Collections.Hashtable.GetEnumerator迭代它们的键值对。

& {
# Output each outer key first, where the names are stored
foreach ($outerKvp in $sections.GetEnumerator()) {
$outerKvp.Key
# Then output each setting and value
foreach ($innerKvp in $outerKvp.Value.GetEnumerator()) {
"$($innerKvp.Key)=$($innerKvp.Value)"
}
}
# Pipe output from script block to output file
} | Out-File -FilePath .output.txt

以上内容将foreach循环封装在Call Operator &内,以运行脚本块并将输出管道传输到Out-File。您可以查看about_Pipelinesabout_Script_Blocks以了解更多信息。

由于我提到了管道和脚本块,我们还可以使用Foreach-Object将输入传递到管道中。从一些初步测试来看,这似乎比上述解决方案稍慢(需要用更大的输入进行进一步研究(。您可以看看Foreach对象与Foreach循环的运行时问题,了解两种方法之间的差异。

$sections.GetEnumerator() | ForEach-Object {
$_.Key
$_.Value.GetEnumerator() | ForEach-Object {
"$($_.Key)=$($_.Value)"
}
} | Out-File -FilePath .output.txt

最后是下面新创建的输出文件。

输出.txt

{name1}
Settinga=1
settingb=2
settingc=3
{name2}
Settinga=1
settingb=2
settingc=3
{name3}
Settinga=1
settingb=4
settingc=3

这表明CCD_ 18的CCD_ 17是从CCD_。

最新更新