首页 > 解决方案 > 使用 Powershell 正则表达式仅替换多个文件中单词的前 8 个实例

问题描述

我有一些 nfo 文件,我想将某个单词的某些实例更改为不同的单词。使用下面我可以这样做,但它当然会改变这个词的所有实例,这不是我需要的。

$Files = Get-ChildItem -Recurse *.nfo
foreach ($File in $Files)
    {
    (Get-Content $File -encoding utf8) -replace 'TextToChange','ReplacedText' | Out-File -encoding utf8 ($File.fullname + '_Changed.nfo')
    }

使用以下内容可以完美地仅替换我想要的单词的前 8 个实例,但我正在努力将其与上面的示例合并。

$MyFile = get-content -encoding utf8 "C:\Temp\OriginalFile.nfo"
[regex]$pattern = "TextToChange"
$pattern.replace($MyFile, "ReplacedText", 8) | Out-File -encoding utf8 "C:\Temp\OriginalFile_Changed.nfo"

我必须接近,但我似乎无法让它与我发现的任何组合一起使用,以将第一个示例的“-replace 'TextToChange','ReplacedText'”部分切换为正则表达式模式从第二个例子。

我需要它遍历文件夹中的所有 NFO 并仅更改每个文件中单词的前 8 个实例,NFO 的数量会有所不同,文件名每次都会不同,所以我不想指定特定的输入文件或一次执行这些。

这可能很容易,我错过了一些愚蠢的事情,但有人可以为我指出正确的方向,或者理想地将两者放在一起,这样可以吗?如果它以尽可能接近第一个示例布局的方式完成,那么所有这些都易于理解并且在我出错的地方尤其明显,但我很乐意接受任何有效的方法。

谢谢

标签: regexpowershellreplace

解决方案


我认为这样的事情可能会奏效:

[RegEx]$Pattern = "TextToChange"

$Files = Get-ChildItem -Recurse *.nfo
foreach ($File in $Files)
{
    $Content = Get-Content $File -Encoding utf8 -Raw 
    $Content = $Pattern.Replace($Content, "ReplacedText", 8)
    
    $Content | Set-Content -Path ($File.FullName + '_Changed.nfo') -Encoding utf8 
}

我应该指出,您计算文件名的方式可能会产生不良结果,例如FileName.nfo_Changed.nfo 查看双扩展名。您可能想改用.BaseName来构造新名称。就像是:

($File.BaseName + '_Changed.nfo')

您可能也可以使用.Extension,但看到您已经过滤,因此知道可能过度杀伤的扩展名。

更新:

另一种略短的写法:

[RegEx]$Pattern = "TextToChange"

$Files = Get-ChildItem -Recurse *.nfo
foreach ($File in $Files)
{
    $Content = Get-Content $File -Encoding utf8 -Raw 
    $Pattern.Replace($Content, "ReplacedText", 8) |     
    Set-Content -Path ($File.FullName + '_Changed.nfo') -Encoding utf8 
}

这只是将替换的输出直接通过管道传输到Set-Content. 但是,我会质疑这是否具有内存效率。看到你已经读过,$Content那么输出.Replace()将需要一个单独的块来馈送管道。


推荐阅读