在配置文件powershell或批处理文件中查找和替换[关闭]

Posted

技术标签:

【中文标题】在配置文件powershell或批处理文件中查找和替换[关闭]【英文标题】:Find and replace in config file powershell or batch file [closed] 【发布时间】:2020-08-22 22:03:45 【问题描述】:

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

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

我希望能够将 name3 下的行 settingb=2 更改为另一个值,例如 settingb=4

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

任何人有任何想法或者这是否可能?

谢谢

【问题讨论】:

你试过什么?在批处理中,您可以使用= 作为分隔符并跟踪每一行的值,如果它是name3 请注意,本网站不是免费的代码/脚本编写服务,而是特定编程相关问题和答案的资源!请(重新)参加tour,访问help center 并在此处了解How to Ask!也请转至minimal reproducible example! 【参考方案1】:

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

我们还可以使用System.String.Split 将行分割为=,这将使用长度来确定该行是名称还是设置。长度 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 将输入传递到管道中。从一些初始测试来看,这似乎比上述解决方案稍慢(需要使用更大的输入进一步调查)。您可以查看这个Runtime of Foreach-Object vs Foreach loop 问题,了解两种方法之间的区别。

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

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

output.txt

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

显示settingbname3 是从24 更新的。

【讨论】:

以上是关于在配置文件powershell或批处理文件中查找和替换[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

比较两个目录,查找同名但内容不同的文件

如何在配置文件中定义的 PowerShell 脚本中设置环境变量?

自动化批处理文件和PowerShell脚本执行

批处理文件或Powershell杀死进程[重复]

如何使用Windows命令行环境查找和替换文件中的文本?

如何使用批处理或PowerShell从文本文件中删除换行符