首页 > 解决方案 > 如何替换文本文件中单个出现的特定单词

问题描述

我有一个 configuration.txt 文件,我的脚本使用它来填充我的脚本中的变量。Tex 文件如下所示:

Setting1= Yes
Setting2= Yes
Setting3= Yes

然后我这样填充我的变量(只提取是或否):

$Setting1=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting1='})
$Setting1=($Setting1 -Split '=', 2)[1].trim()

$Setting2=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting2='})
$Setting2=($Setting2 -Split '=', 2)[1].trim()

$Setting3=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting3='})
$Setting3=($Setting3 -Split '=', 2)[1].trim()

然后我有一些逻辑,如果用户通过我的脚本中的提示更改这些设置,脚本将使用以下代码更新文本文件:

((Get-Content -Path .\configuration.txt -Raw | Where-Object {$_ -match 'Setting1'}) -replace $Setting1, $UserSetting1) | Set-Content -Path .\configuration.txt

其中 $UserSetting1 是用户的输入(“是”或“否”)。

现在这样做是更改配置文件中的每个“是”或“否”,而不是仅更改我尝试使用匹配功能拉出的特定行上的“是”或“否”。

换句话说,如果用户想要将设置 1 更改为“否”并将设置 2 和 3 保持为“是”;该脚本将所有设置更改为是,而不仅仅是设置1。

我的印象是我必须使用 -Raw 才能执行 -replace,但如上所述,似乎 -match 函数不适用于 -Raw 函数......如果我不使用-raw,然后我的配置文件只用我匹配的单行重写。

标签: powershellreplacefile-get-contents

解决方案


您可以只使用Replace Operator进行更新。

$UserSetting1 = 'No'
(Get-Content -Path .\configuration.txt) -replace '(?<=Setting1=).*',$UserSetting1 |
    Set-Content

由于-replace使用正则表达式匹配机制,您可以构造匹配以仅返回要替换的数据。替换字符串可以是变量。有关正则表达式的说明,请参见下文。它匹配后面一行上的剩余字符Setting1=,然后用存储在 中的值替换这些字符$UserSetting1。不匹配的行将按原样返回,无需替换。

  • (?<=)是正则表达式肯定的后向断言。它断言在字符串中的给定位置后面有一个完全匹配。
  • Setting1=字符串的文字匹配Setting1=
  • .*尽可能多的字符,直到字符串结尾(就在换行符之前)[1]

使用-Raw开关将文件内容作为单个字符串读取。如果您-match对具有匹配项的单个字符串执行正则表达式匹配 ( ),$true则返回。整个字符串被视为匹配项,默认捕获组 0。$matches[0]包含该匹配项。因此,如果您使用-replace替换该匹配项中的子字符串,它将替换该子字符串中满足匹配条件的每个实例。-replace

如果-Raw不使用该开关,则将文件内容作为行数组读入。-replace单独仍然会替换匹配的每个实例。但是,您现在可以使用-matchWhere-Object为某些匹配的行执行不同的代码。

结合-match-replace不结合-Raw可能只会导致您读取数据的一个子集。当您处理文件的每一行时,在处理任何替换之前-match基本上会过滤掉任何不返回的行。这种情况适用于返回替换,但在您尝试重写整个文件时可能会导致问题。您将需要额外的逻辑来跟踪您拥有和未修改的数组元素,并在更新内容时适当地输出它们。$true


[1]如果正则表达式模式为单行,则. 可以匹配换行符。-replace您可以在正则表达式中启用此模式,方法是使用(?s).


推荐阅读