替换String而不替换文件powershell的整个内容

时间:2017-04-25 00:46:18

标签: powershell

尝试编辑文件的这一行(“VoIP.Enabled”1“)。我想将1更改为零。当我用

更改它时
$dewprefs = Get-Content .\dewrito_prefs.cfg

$dewprefs | Select-String "VoIP.Enabled" | ForEach-Object {$_ -replace "1","0"} | Set-Content .\dewrito_prefs.cfg}`

然而,当我使用这个脚本时,它会移除100个其他行,编辑右边的行,然后删除其他所有内容,只留下我想编辑的行。

对此事的任何帮助都将受到高度赞赏

2 个答案:

答案 0 :(得分:2)

Select-String充当过滤器:也就是说,只有匹配模式时,才会传递给定的输入。

因此,将感兴趣的行写入输出文件。

如果所有输入行 - 尽管可能已修改 - 应该通过,请不要使用Select-String;仅使用 ForEach-Object,并且有条件地修改每个输入行:

$dewprefs = Get-Content .\dewrito_prefs.cfg

$dewprefs |
  ForEach-Object { if ($_ -match 'VoIP\.Enabled') { $_ -replace '1', '0' } else { $_ } } | 
    Set-Content .\dewrito_prefs.cfg

$_ -match 'VoIP\.Enabled'现在执行Select-String在原始命令中执行的操作:仅当手头的输入行包含文字VoIP.Enabled时才会匹配(请注意.如何转义为\.以确保在正则表达式的上下文中将其视为文字

注意if语句的两个分支如何产生输出

  • $_ -replace '1', '0'输出使用1

  • 替换输入行中0的所有实例的结果
  • $_只是按原样传递输入行。

然而,最有可能的是,您可以使用单个if表达式替换-replace语句,并且假设该文件足够小以便作为整体读取(很可能,在配置文件),您可以使用Stu's helpful simplification的变体。

充分利用-replace支持正则表达式(正则表达式)的事实,代码可以仅基于密钥名称(例如VoIP.Enabled)更新行,而无需知道密钥的当前值。

$key = 'VoIP.Enabled'
$newValue = '1'

# Construct a regex that matches the entire target line.
$regex = '^\s*' + [regex]::Escape($key) + '\b.*$'
# Build the replacement line.
$modifiedLine = "$key $newValue"

(Get-Content .\dewrito_prefs.cfg) -replace $regex, $modifiedLine | Set-Content .\dewrito_prefs.cfg

请注意,将输出写回输入文件只能起作用,因为输入文件作为一个整体,在前面被读入内存,因为Get-Content调用了(...) 1}}。

答案 1 :(得分:2)

这也适用于PowerShell v3 +,并且更简洁:

(Get-Content .\dewrito_prefs.cfg).replace('"VoIP.Enabled "1"', '"VoIP.Enabled "0"') | 
    Set-Content .\dewrito_prefs.cfg

你的报价有点奇怪(总共3个双引号?),但我已经模仿了你所问的内容。