簡體   English   中英

用powershell替換文件夾中所有文件中的字符串

[英]Replace string in all files of a folder with 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中的文檔名稱都顯示在頂部)。

因此,我知道很多信息(但是我想提供盡可能多的信息),很抱歉,如果我不清楚,但是基本上我想使上面的代碼適用於文件夾中的每個文件。

提前致謝!

所以我找到了解決方案

首先,我在那里遇到問題

$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嘗試從當前目錄訪問文件

$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"
}

由於您沒有包括整個文件,因此我創建了一個簡單的source.html文件:

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

接下來的問題是解析HTML 如評論中所述,regexp 不是解析html的好方法。 在我看來,如果您的HTML頁面/網站相當復雜,最好的解決方案是使用最初用於.NET的 html敏捷包 ,但也可以針對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
}

我希望源代碼清晰,我已嘗試使其具有可讀性(不要忘記更改所有變量)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM