如何替换文本文件中出现的特定单词
How to replace a single occurrence of a specific word in a text file
我有一个 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 是用户的输入('yes' 或 'no')。
现在所做的是更改配置文件中的每个 'yes' 或 'no' 而不是仅更改我所在的特定行上的 'yes' 或 'no'尝试用匹配功能拉出来
换句话说,如果用户想要将设置 1 更改为 'no' 并将设置 2 和 3 保留为 'yes';脚本正在将所有设置更改为是,而不仅仅是设置 1。
我的印象是我必须使用 -Raw 才能执行 -replace,但如上所述,-match 函数似乎不适用于 -Raw 函数......并且如果我不使用 -raw,那么我的配置文件将只用我匹配的一行重新编写。
您可以直接使用 Replace Operator 进行更新。
$UserSetting1 = 'No'
(Get-Content -Path .\configuration.txt) -replace '(?<=Setting1=).*',$UserSetting1 |
Set-Content
由于 -replace
使用正则表达式匹配机制,您可以构建仅 return 要替换的数据的匹配。替换字符串可以是一个变量。请参阅下面的正则表达式解释。它匹配 Setting1=
之后一行的剩余字符,然后用存储在 $UserSetting1
中的值替换这些字符。没有匹配项的行将 return 原样编辑,不进行替换。
(?<=)
是正则表达式正向回顾断言。它断言在字符串中的给定位置后面有一个完全匹配项。
Setting1=
字符串 Setting1=
. 的文字匹配
.*
尽可能多的字符直到字符串结尾(就在换行符之前)[1].
使用 -Raw
开关将文件内容作为单个字符串读取。如果您对具有匹配项的单个字符串执行正则表达式匹配 (-match
),则 $true
被 returned。整个字符串被视为一个匹配项,默认为捕获组 0。$matches[0]
包含该匹配项。因此,如果您使用 -replace
替换该匹配项中的子字符串,它将替换满足 -replace
匹配条件的该子字符串的 每个 实例。
如果不使用-Raw
开关,则文件内容作为行数组读入。 -replace
单独仍然会替换匹配项的每个实例。但是,您现在可以使用 -match
和 Where-Object
为某些匹配的行执行不同的代码。
在没有 -Raw
的情况下组合 -match
和 -replace
可能只会导致读取数据的一个子集。当您处理文件的每一行时,-match
将在您处理任何替换之前 return $true
实质上过滤掉任何行。这种情况适合 return 替换,但在您尝试重写整个文件时可能会导致问题。您将需要额外的逻辑来跟踪您已经修改和未修改的数组元素,并在您更新内容时适当地输出它们。
[1] .
如果正则表达式模式是单行,则可以 匹配换行符。您可以在 -replace
正则表达式中以 (?s)
.
开头启用此模式
另一种方法是读取配置文件并将 name/value 对存储在哈希表中。
如果设置在文本文件中的显示顺序不重要,您可以使用 ConvertFrom-StringData
cmdlet。
这将解析设置名称和值,并将其 returns 作为哈希表。
$config = Get-Content -Path .\configuration.txt -Raw | ConvertFrom-StringData
如果顺序 确实 重要,请创建一个有序哈希(需要 PowerShell 3.0 或更高版本):
$config = [ordered]@{}
Get-Content -Path D:\configuration.txt | ForEach-Object {
$name, $value = ($_ -split '=' , 2).Trim()
$config[$name] = $value
}
如果用户想要将 Setting1
的值更改为 no
例如($UserSetting1='no'),只需执行:
$UserSetting1 = 'no'
$config.Setting1 = $UserSetting1
# Next save the updated settings back to the textfile
$newContent = foreach($name in $config.Keys) {
'{0} = {1}' -f $name, $config.$name
}
$newContent | Set-Content -Path .\configuration.txt -Force
我有一个 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 是用户的输入('yes' 或 'no')。
现在所做的是更改配置文件中的每个 'yes' 或 'no' 而不是仅更改我所在的特定行上的 'yes' 或 'no'尝试用匹配功能拉出来
换句话说,如果用户想要将设置 1 更改为 'no' 并将设置 2 和 3 保留为 'yes';脚本正在将所有设置更改为是,而不仅仅是设置 1。
我的印象是我必须使用 -Raw 才能执行 -replace,但如上所述,-match 函数似乎不适用于 -Raw 函数......并且如果我不使用 -raw,那么我的配置文件将只用我匹配的一行重新编写。
您可以直接使用 Replace Operator 进行更新。
$UserSetting1 = 'No'
(Get-Content -Path .\configuration.txt) -replace '(?<=Setting1=).*',$UserSetting1 |
Set-Content
由于 -replace
使用正则表达式匹配机制,您可以构建仅 return 要替换的数据的匹配。替换字符串可以是一个变量。请参阅下面的正则表达式解释。它匹配 Setting1=
之后一行的剩余字符,然后用存储在 $UserSetting1
中的值替换这些字符。没有匹配项的行将 return 原样编辑,不进行替换。
(?<=)
是正则表达式正向回顾断言。它断言在字符串中的给定位置后面有一个完全匹配项。Setting1=
字符串Setting1=
. 的文字匹配
.*
尽可能多的字符直到字符串结尾(就在换行符之前)[1].
使用 -Raw
开关将文件内容作为单个字符串读取。如果您对具有匹配项的单个字符串执行正则表达式匹配 (-match
),则 $true
被 returned。整个字符串被视为一个匹配项,默认为捕获组 0。$matches[0]
包含该匹配项。因此,如果您使用 -replace
替换该匹配项中的子字符串,它将替换满足 -replace
匹配条件的该子字符串的 每个 实例。
如果不使用-Raw
开关,则文件内容作为行数组读入。 -replace
单独仍然会替换匹配项的每个实例。但是,您现在可以使用 -match
和 Where-Object
为某些匹配的行执行不同的代码。
在没有 -Raw
的情况下组合 -match
和 -replace
可能只会导致读取数据的一个子集。当您处理文件的每一行时,-match
将在您处理任何替换之前 return $true
实质上过滤掉任何行。这种情况适合 return 替换,但在您尝试重写整个文件时可能会导致问题。您将需要额外的逻辑来跟踪您已经修改和未修改的数组元素,并在您更新内容时适当地输出它们。
[1] .
如果正则表达式模式是单行,则可以 匹配换行符。您可以在 -replace
正则表达式中以 (?s)
.
另一种方法是读取配置文件并将 name/value 对存储在哈希表中。
如果设置在文本文件中的显示顺序不重要,您可以使用 ConvertFrom-StringData
cmdlet。
这将解析设置名称和值,并将其 returns 作为哈希表。
$config = Get-Content -Path .\configuration.txt -Raw | ConvertFrom-StringData
如果顺序 确实 重要,请创建一个有序哈希(需要 PowerShell 3.0 或更高版本):
$config = [ordered]@{}
Get-Content -Path D:\configuration.txt | ForEach-Object {
$name, $value = ($_ -split '=' , 2).Trim()
$config[$name] = $value
}
如果用户想要将 Setting1
的值更改为 no
例如($UserSetting1='no'),只需执行:
$UserSetting1 = 'no'
$config.Setting1 = $UserSetting1
# Next save the updated settings back to the textfile
$newContent = foreach($name in $config.Keys) {
'{0} = {1}' -f $name, $config.$name
}
$newContent | Set-Content -Path .\configuration.txt -Force