【问题标题】:Powershell replace part of content of one file by content of another filePowershell用另一个文件的内容替换一个文件的部分内容
【发布时间】:2017-07-10 20:47:02
【问题描述】:

我有包含以下内容的 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 代码来更新关键字 --start--end 之间的 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 在一行中包含关键字 --start--end 并且 relult 紧随其后时才有效(插入的内容没有结束符) :

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

【问题讨论】:

  • 你有什么要开始的吗? “请为我写代码”的帖子通常不受欢迎。如果您也理解正确的代码,它将更加有用。
  • 我已经更新了我的问题。

标签: powershell


【解决方案1】:

这有点牵扯,因为你需要用 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
}

说明:

Get-Content-Raw 开关告诉 cmdlet 将所有内容作为一个字符串获取,而不是像通常那样使用一组行。

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

现在,解释一下正则表达式:

"(?s)(--start`r`n).*?(`r`n--end)"

(?s) 是单行模式的regular expression option。这意味着. 字符将匹配行尾。通常不会。

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

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

替换字符串:

"`$1$contentStart`$2"

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

【讨论】:

  • 它给了我空的输出文件。
【解决方案2】:

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

您需要告诉 RegEx:

  • m 标记 ^$ 匹配行开始/结束
  • 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

【讨论】:

  • 我确实比我更喜欢你的正则表达式。我忘记了多行选项。我不确定它是否会删除 --start--end 行?
猜你喜欢
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2014-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
相关资源
最近更新 更多