在不使用正则表达式的情况下,使用PowerShell替换文件中的多行文本

5
我有以下 PowerShell 脚本:
$oldCode =  @"
            <div id="time_estimate">
                <!-- some large table -->
            </div>
"@

$newCode = @"
            <div id="time_estimate">
                                <!-- nested divs and spans -->
                                <div id="contact-form">

                                        <?php include "contact-form.php"; ?>
                                </div>
                        </div>
"@

ls *.html | foreach { 
        $fileContent = [System.Io.File]::ReadAllText($_.FullName)
        $newFileContent = $fileContent.Replace($oldCode, $newCode)
        [System.Io.File]::WriteAllText($_.FullName, $newFileContent)
        Write-Host  "`r`n"
        Write-Host  "Processed - $($_.Name)...`r`n" }

这似乎没有替换文本。是多行字符串的问题,还是Replace()方法的限制?我希望能够在不使用正则表达式的情况下进行替换。

3个回答

5
你正在使用哪个版本的PowerShell?如果你正在使用v3或更高版本,请尝试以下内容:
ls *.html | foreach { 
    $fileContent = Get-Content $_.FullName -Raw
    $newFileContent = $fileContent -replace $oldCode, $newCode
    Set-Content -Path $_.FullName -Value $newFileContent
    Write-Host  "`r`n"
    Write-Host  "Processed - $($_.Name)...`r`n" 
}

这基本上是我处理问题的方式。-Raw开关是Powershell v3的一个不错的补充。在v2中,我经常依赖于Get-Content <file> | Out-String来实现类似的结果。在这个答案中有更多细节相关的问题。 - ajk
我升级到了版本3并应用了这种方法。 - KalenGi
1
如果有人想要一个处理单个文件的一行代码,可以像这样写: (Get-Content -raw file.txt) -replace $oldCode, $newCode | Set-Content file.txt - Henrik

1

别傻了,千万别试图用正则表达式处理HTML。

你遇到的问题是读取文件会提供一个字符串数组。 Replace() 不知道如何处理数组,所以你必须手动处理。你可以使用 -join 创建一个大字符串,方法如下:

$fileContent = [System.Io.File]::ReadAllText($_.FullName)
$theOneString = $fileContent -join ' '
$theOneString.Replace($foo, $bar)

...但这样会破坏你的换行符。不过,你可以使用HTML Tidy重新格式化字符串。

手动的方法是逐行迭代源数组。直到找到<div>,将内容复制到新的目标数组中。在找到可替换部分后,将其余的新内容插入到目标数组中。继续阅读和丢弃源数组,直到找到</div>并将所有剩余内容复制到目标数组中。最后保存目标数组的内容,你就完成了。


1
非常感谢您提供那个滑稽答案的链接!笑声帮了我很多... - KalenGi

1
我不会使用字符串替换来修改HTML代码。有太多的事情可能会朝着意料之外的方向发展。尝试使用类似以下的方法:
$newCode = @"
<!-- nested divs and spans -->
<div id="contact-form">
  <?php include "contact-form.php"; ?>
</div>
"@

Get-ChildItem '*.html' | % {
  $html = New-Object -COM HTMLFile
  $html.write([IO.File]::ReadAllText($_.FullName))
  $html.getElementById('time_estimate').innerHTML = $newCode
  [IO.File]::WriteAllText($_.FullName, $html.documentElement.outerHTML)
}

如果需要,您可以使用Tidy来美化HTML:

$newCode = @"
<!-- nested divs and spans -->
<div id="contact-form">
  <?php include "contact-form.php"; ?>
</div>
"@

[Reflection.Assembly]::LoadFile('C:\path\to\Tidy.dll') | Out-Null
$tidy = New-Object Tidy.DocumentClass

Get-ChildItem '*.html' | % {
  $html = New-Object -COM HTMLFile
  $html.write([IO.File]::ReadAllText($_.FullName))
  $html.getElementById('time_estimate').innerHTML = $newCode
  $tidy.ParseString($html.documentElement.outerHTML)
  $tidy.SaveFile($_.FullName) | Out-Null
}

这实际上是有效的,但会通过剥离前导空格来干扰文档的格式。 - KalenGi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接