Powershell用另一个文件的内容替换一个文件的部分内容

时间:2017-07-10 20:47:03

标签: powershell

我的text1.txt文件包含以下内容:

sometext_1
--start
sometext_2.1
sometext_2.2
...
sometext_2.n
--end
sometext_3

和text2.txt文件包含以下内容:

--start
sometext_2_new1
sometext_2_new2
...
sometext_2_newn
--end

有人可以帮我编写Powershell代码来更新关键字 - 开始 - 结束之间的text1.txt文件内容以及文件text2.txt的所有内容? 所以新的text1.txt将如下所示:

sometext_1
--start
sometext_2_new1
sometext_2_new2
...
sometext_2_newn
--end
sometext_3

更新 我是Powershell的新人。经过一些研究,我得出了以下内容,但仍然没有给我我需要的东西:

param(
[string]$location
)

$contentStart = Get-Content "c:\text2.txt"

$configFiles = Get-ChildItem $location\*.txt -rec
foreach ($file in $configFiles)
{
    (Get-Content $file.PSPath) |
    Foreach-Object { $_ -replace "--start.*?(--end)", $contentStart } |
    Out-File $file.PSPath
}

但仅当text1.txt在一行中包含关键字 - 开始 - 结束并且relult正在关注(插入的内容没有结束符号)时,它才有效:

sometext_1
--start sometext_2_new1 sometext_2_new2 ... sometext_2_newn --end
sometext_3

2 个答案:

答案 0 :(得分:3)

它有点牵扯,因为您需要使用SingleLine模式创建正则表达式。

尝试这样的事情:

foreach ($file in $configFiles)
{
    Get-Content $file.PSPath -Raw |
    ForEach-Object { $_ -replace "(?s)(--start`r`n).*?(`r`n--end)", "`$1$contentStart`$2" } |
    Out-File $file.PSPath
}

<强>解释

-Raw的{​​{1}}开关告诉cmdlet将所有内容都作为一个单独的字符串,而不是像通常那样的行数组。

现在每个文件只有一个项目通过管道,但我们仍然需要Get-Content cmdlet来为我们枚举项目。

现在,解释正则表达式:

ForEach-Object

"(?s)(--start`r`n).*?(`r`n--end)" 是单行模式的regular expression option。这意味着(?s)字符将匹配行结尾。通常它没有。

接下来,还有正则表达式的其余部分.(--start`r`n).*?(`r`n--end)--start非常明显。对于大多数其他语言的回车,Windows行结束字符--end表示为`r,而大多数其他语言的行结束时\r`n。需要包含它们,以便\n不要在单线模式下吃掉它们。括号用于分组反向引用。第一个括号组将成为.*?,第二个成为$1等。

请注意,如果您的文本文件未使用Windows行结尾,则可能需要相应地修改此正则表达式。

替换字符串:

$2

在这里,我们使用双引号,以便PowerShell变量"`$1$contentStart`$2" 可以内联到字符串中。并且$contentStart$1作为正则表达式中的组的反向引用变量存在。但是,我们遇到了反向引用变量的问题。它们是$2$1,它们是PowerShell中的有效变量。所以,我们需要用另一个反击来逃避美元符号。

答案 1 :(得分:2)

我喜欢Regex101.com测试和改进我开发的正则表达式 见here your example

您需要告诉RegEx:

  • ^标记$s匹配行开头/结尾
  • .标记PS> $text1 = Get-Content ".\text1.txt" PS> $text2 = Get-Content ".\text2.txt" PS> $text1 -replace "(?ms)^--start$.*?^--end$",$text2 sometext_1 --start sometext_2.1 sometext_2.2 ... sometext_2.n --end sometext_3 点也匹配新行
{{1}}