用powershell替换文件夹的所有文件中的字符串

时间:2018-04-03 09:41:53

标签: powershell

我刚刚开始使用Powershell,因为我需要创建一个脚本,将链接放在文件夹的所有文件(htm文件)中。这些链接实际上链接了它们之间的所有文件。 我有一个文件夹中的文件列表(此文件名为list.txt,包含没有扩展名的文件的名称)

在每个文件中,我想进行以下更改:

自:

  

<tspan x="53" y="54.8">Surveillance_Err_PRG</tspan>

要:

  

<tspan x="53" y="54.8"><a href="C:/[...path...]/HTMs/Surveillance_Err_PRG.htm">Surveillance_Err_PRG</a></tspan>

经过一些研究,我编写了以下代码,但它没有做任何事情(输出只显示我的代码):

$directory = "C:\Users\jacka\Desktop\Organigramme_PLC_prog_test\"
$list = "$directory" + "list.txt"
$htms = "$directory" + "HTMs"   

$htmFiles = Get-ChildItem $directory *.htm -rec
foreach ($file in $htmFiles)
{
    foreach($line in Get-Content $list)
    {
        if($line -match $regex)
        {
            $fichier = "$htms\"+"$line"+".htm"

            (Get-Content $file.PSPath) |
            Foreach-Object { $_ -replace "$line", "<a href=""$htms\$line"">$line</a>" } |
            Set-Content $file.PSPath
         }
         echo $fichier
    }
}

在那之前,我有这样的话:

foreach($line in Get-Content $list) {
    if($line -match $regex){
        $fichier = "$htms\"+"$line"+".htm"
        (Get-Content $fichier).replace("$line", "<a href=""$fichier"">$line</a>") | Set-Content $fichier
        echo $fichier
    }
}

它没有真正起作用,因为它只是在内部标题上放置一个链接(在每个htm中,顶部显示的文档名称)。

所以我知道有很多信息(但我想提供尽可能多的信息),如果我不清楚,我很抱歉,但基本上我想让上面的代码适用于每个文件我的文件夹。

提前致谢!

2 个答案:

答案 0 :(得分:2)

所以我找到了解决方案

首先,我遇到了问题

$htmFiles = Get-ChildItem $directory *.htm -rec
    foreach ($file in $configFiles)

变量不一样,但后来我收到了这个错误:

C:\Users\jacka\Desktop\Organigramme_PLC_prog_test\HTMs\Systeme_Filtration_Prg.htm
Get-Content : Impossible de trouver le chemin d'accès « C:\Users\jacka\ChargementProg_PRG.htm », car il n'existe pas.
Au caractère Ligne:22 : 14
+             (Get-Content $file) |
+              ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\jacka\ChargementProg_PRG.htm:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

我通过在$ file之后添加.FullName解决了这个问题,该文件阻止了Get-Content trying to access the file from current directory

$htmFiles = Get-ChildItem $directory *.htm -rec
foreach ($file in $htmFiles)
{

    foreach($line in Get-Content $list)
    {
        if($line -match $regex)
        {
            $fichier = "$directory"+"$line"+".htm"
            if ($file.FullName -ne $fichier) #to prevent header to be changed
            {
                (Get-Content $file.FullName) |
                Foreach-Object { $_ -replace "$line", "<a href=""$fichier"">$line</a>" } |
                Set-Content $file.FullName
            }
         }
    }
    echo "$file.FullName is done"
}

答案 1 :(得分:2)

由于您没有包含整个文件,因此我创建了一个简单的source.html文件:

<html>
<head>
<title>Website</title>
</head>
<body>
<tspan x="53" y="54.8">Surveillance_Err_PRG</tspan>
</body>
</html>

接下来,您遇到的问题是解析 HTML 。正如评论中所述,regexp是 NOT 解析html的好方法。在我看来,如果你有一个相当复杂的html页面/网站等,最好的解决方案是使用最初用于 .NET html agility pack,但也可以针对powershell进行调整。

要获得最终结果的示例,您必须这样做: (注意:不要忘记更改 HtmlAgilityPack.dll 的路径)

Add-Type -Path 'C:\prg_sdk\nuget\HtmlAgilityPack.1.7.2\lib\Net40-client\HtmlAgilityPack.dll'

$doc = New-Object HtmlAgilityPack.HtmlDocument
$result = $doc.Load('C:\prg\PowerShell\test\SO\source.html')

$text = $doc.DocumentNode.SelectNodes("//tspan").InnerHTML
write-host $text

$out_text = $doc.DocumentNode.SelectNodes("//tspan").OuterHTML
write-host $out_text

$element = $doc.CreateTextNode("<a href=""c:\<your_path>\HTMs\$text.htm"">$text</a>")
$doc.DocumentNode.SelectSingleNode("//tspan").InnerHTML = $element.InnerText

$changed_text = $doc.DocumentNode.SelectSingleNode("//tspan").OuterHTML
Write-host "Adjusted text:" $changed_text

write-host 'whole HTML:' $doc.DocumentNode.SelectSingleNode("//tspan").OuterHtml

# To overview whole HTML
write-host 'whole HTML:' $doc.DocumentNode.InnerHTML

写主机将产生你的希望:

<tspan x="53" y="54.8"><a href="c:\<your_path>\HTMs\Surveillance_Err_PRG.htm">Surveillance_Err_PRG</a></tspan>

要在文件中查找字符串,您可以执行以下操作(只是一个代码段):

$html_files= Get-ChildItem . *.htm -rec
foreach ($file in $html_files)
{
    (Get-Content $file.PSPath) |
    Foreach-Object { $_ -replace "$out_text", "$changed_text" } |
    Set-Content $file.PSPath
}

要将它组合在一起,您必须遍历所有.htm文件并将其替换为上述示例。如果您希望我们完成它,您将不得不给我整个文件示例。我在测试一个时做到了:

现在所有人都看起来像这样:

Add-Type -Path 'C:\prg_sdk\nuget\HtmlAgilityPack.1.7.2\lib\Net40-client\HtmlAgilityPack.dll'

$doc = New-Object HtmlAgilityPack.HtmlDocument
$result = $doc.Load('C:\prg\PowerShell\test\SO\source.html')

$text = $doc.DocumentNode.SelectNodes("//tspan").InnerHTML

$original_tag = $doc.DocumentNode.SelectNodes("//tspan").OuterHTML

$element = $doc.CreateTextNode("<a href=""c:\<your_path>\HTMs\$text.htm"">$text</a>")
$doc.DocumentNode.SelectSingleNode("//tspan").InnerHTML = $element.InnerText

$changed_tag = $doc.DocumentNode.SelectSingleNode("//tspan").OuterHTML

$html_files= Get-ChildItem . *.htm -rec
foreach ($file in $html_files)
{
    (Get-Content $file.PSPath) |
    Foreach-Object { $_ -replace "$original_tag", "$changed_tag" } |
    Set-Content $file.PSPath
}

我希望源代码是清楚的,我试图使其可读(不要忘记更改所有变量)。