我的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
答案 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}}