如何使用PowerShell替换文件中的行?

时间:2016-11-18 14:11:23

标签: powershell

我正在尝试使用PowerShell读取配置文件中的一行。有时这个脚本有效,但大多数时候它不会替换该行。

(Get-Content D:\home\App_Config\Sitecore.config) `
    | %{ $_ -replace '  <setting name="Media.MediaLinkServerUrl" value=" "/>',' <setting name="Media.MediaLinkServerUrl" value="https://newurl.com"/>'} `
    | Set-Content D:\home\App_Config\Sitecore.config

4 个答案:

答案 0 :(得分:21)

尝试以下方法:

$file = 'D:\home\App_Config\Sitecore.config'
$regex = '(?<=<setting name="Media\.MediaLinkServerUrl" value=")[^"]*'
(Get-Content $file) -replace $regex, 'https://newurl.com' | Set-Content $file

*重新Set-Content:它默认使用您系统的传统单字节字符编码,因此您可能希望使用-Encoding来控制输出文件&#39;明确编码。
*另请注意(...)调用所需的Get-Content,以确保管道可以回写Get-Content已读取的同一文件。
*如果有问题的开头标记(<setting ...>)跨越多行,则使用
Get-Content -Raw $file(PSv3 +)将整个文件内容读作单字符串(谢谢,deadlydog);
如果没有-RawGet-Content会返回字符串的数组,表示输入

由于使用正则表达式来匹配您现有的设置,因此当前value="..."内的任何文本都匹配,因此即使重复运行,此命令也能正常工作

相比之下,您尝试的内容使用有效的文字... value=" ")来查找要替换的内容,并且在第一次成功运行之后,文字不再匹配,后续运行失败。

上述命令使用简化的替换方法:

  • (?<=<setting name="Media.MediaLinkServerUrl" value=")是一个后视断言((?<=...))匹配,但没有捕获它匹配的内容:它找到包含开头{{ 1}}您尝试替换的价值,而不会将该前缀作为替换内容的一部分。

  • "然后匹配整个值,但不包括结束[^"]*。 ("是一个字符集,匹配任何字符其他而不是[^"])和^"找到任何(可能为空)序列这些人物。

  • 因此,由于正则表达式仅捕获了值本身,因此您需要指定为替换字符串的是新值。

答案 1 :(得分:13)

使用这样的替换方法:

$file = 'D:\home\App_Config\Sitecore.config'
$find = '  <setting name="Media.MediaLinkServerUrl" value=" "/>'
$replace = ' <setting name="Media.MediaLinkServerUrl" value="https://newurl.com"/>'

(Get-Content $file).replace($find, $replace) | Set-Content $file

答案 2 :(得分:0)

此功能对我有用

我正在尝试替换Infile之后的所有内容 enter image description here

功能:

function Write-FileContent {
        [cmdletBinding()]
        param(
            [parameter(Mandatory = $true)]
            [string]$FileToReplacePath,
            [parameter(Mandatory = $true)]
            [string]$TextToReplaceWith,
            [parameter(Mandatory = $true)]
            [string]$LineNumber,
            [parameter(Mandatory = $true)]
            [string]$TextToBeingWith        
        )
        $Read = Get-Content -Path $FileToReplacePath
        $Read | ForEach-Object { if ($_.ReadCount -eq $LineNumber) { $_ -replace "'$TextToBeginWith'=.+'", "$TextToReplaceWith" }   else { $_ } } | Set-Content $FileToReplacePath
    }

测试参数

$CsvFilePath="C:\msydatfgdfa.csv"
Write-FileContent -FileToReplacePath D:\test.txt -TextToReplaceWith "'$CsvFilePath'" -LineNumber 2 -TextToBeingWith "Infile"

答案 3 :(得分:0)

下面是保留PSPath属性的示例,因此您不必指定set-content的路径:

   product_no part_no  level  last_part_no
0           1     1_1      1           nan
1           1     1_2      1           nan
2           1     1_3      2           1_2
3           1     1_4      1           nan
4           1     1_5      1           nan
5           1     1_6      2           1_5
6           1     1_7      2           1_5
7           1     1_8      3           1_7
8           1     1_9      3           1_7
9           1    1_10      2           1_5