簡體   English   中英

PowerShell:替換目錄內 all.txt 文件中的字符串

[英]PowerShell: Replace string in all .txt files within directory

我正在嘗試替換目錄中字符串的每個實例。 但是我的代碼沒有替換任何東西。

到目前為止我所擁有的:

測試文件夾包含多個文件和文件夾,其中包含我需要更改的內容。 文件夾包含 .txt 文檔,.txt 文檔包含如下字符串: Content reference=".​​./../../PartOfPath/EN/EndofPath/Caution.txt" 我需要更改為: Content reference= “../../../PartOfPath/FR/EndofPath/Caution.txt”

在提出這個問題之前,是的,必須以這種方式完成,因為還有其他類似的字符串我不想編輯。 所以我不能只用 FR 替換 EN 的所有實例。

$DirectoryPath = "C:\TestFolder"

$Parts =@(
@{PartOne="/PartOfPath";PartTwo="EndofPath/Caution.txt"},
@{PartOne="/OtherPartOfPath";PartTwo="EndofPath/Note.txt"},
@{PartOne="/ThirdPartOfPath";PartTwo="OtherEndofPath/Warning.txt"}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }

Get-ChildItem $DirectoryPath | ForEach {
    foreach($n in $Parts){
        [string]$PartOne = $n.PartOne
        [string]$PartTwo = $n.PartTwo
        $ReplaceThis = "$PartOne/EN/$PartTwo"
        $WithThis = "$PartOne/FR/$PartTwo"
        (Get-Content $_) | ForEach  {$_ -Replace $ReplaceThis, $WithThis} | Set-Content $_
    }
}

代碼將運行並覆蓋文件,但不會進行任何編輯。

在進行故障排除時,我遇到了這個潛在的原因:

該測試有效:

$FilePath = "C:\TestFolder\Test.txt"

$ReplaceThis ="/PartOfPath/EN/Notes/Note.txt"
$WithThis = "/PartOfPath/FR/Notes/Note.txt"

(Get-Content -Path $FilePath) -replace $ReplaceThis, $WithThis | Set-Content $FilePath

但是這個測試沒有

$FilePath = "C:\TestFolder\Test.txt"
foreach($n in $Parts){
    [string]$PartOne = $n.PartOne
    [string]$PartTwo = $n.PartTwo

    [string]$ReplaceThis = "$PartOne/EN/$PartTwo"
    [string]$WithThis = "$PartOne/FR/$PartTwo"

    (Get-Content -Path $FilePath) -replace $ReplaceThis, $WithThis | Set-Content $FilePath
}

如果您能幫助我了解這里出了什么問題,我將不勝感激。

感謝@TessellatingHeckler 的評論,我修改了我的代碼並找到了這個解決方案:

$DirectoryPath = "C:\TestFolder"

$Parts =@(
@{PartOne="/PartOfPath";PartTwo="EndofPath/Caution.txt"},
@{PartOne="/OtherPartOfPath";PartTwo="EndofPath/Note.txt"},
@{PartOne="/ThirdPartOfPath";PartTwo="OtherEndofPath/Warning.txt"}) | % { New-Object object | Add-Member -NotePropertyMembers $_ -PassThru }

Get-ChildItem $LanguageFolderPath -Filter "*.txt" -Recurse | ForEach {
    foreach($n in $Parts){
        [string]$PartOne = $n.PartOne
        [string]$PartTwo = $n.PartTwo
        $ReplaceThis = "$PartOne/EN/$PartTwo"
        $WithThis = "$PartOne/FR/$PartTwo"
        (Get-Content $_) | ForEach  {$_.Replace($ReplaceThis, $WithThis)} | Set-Content $_
    }
}

有2個問題:

1: -replace 沒有按我的預期工作,所以我不得不改用.replace

2:原來的 Get-ChildItem 沒有返回任何值,必須用上面的版本替換。

謝謝你的幫助。

  • 默認情況下,PowerShell 的-replace運算符是基於正則表達式且不區分大小寫的:

    • 要執行文字替換, \ -轉義模式中的元字符或調用[regex]::Escape()
  • 相比之下, [string]類型的.Replace()方法執行文字替換並且區分大小寫始終在 Windows PowerShell 中,默認情況下在 PowerShell 中(有關更多信息,請參閱此答案7+)

所以:

  • 正如TessellatingHeckler指出的那樣,鑒於您的搜索字符串似乎包含需要 escaping 的正則表達式元字符(例如.\ ),因此沒有明顯的原因說明您的原始方法不起作用。

  • Given that you're looking for literal substring replacements, the [string] type's .Replace() is generally the simpler and faster option if case-SENSITIVITY is desired / acceptable (invariably so in Windows PowerShell; as noted, in PowerShell (Core) 7+,您也可以選擇使.Replace()不區分大小寫)。

  • 但是,由於您需要執行多次替換,因此可以使用更簡潔的單遍-replace解決方案(盡管必須測試它是否實際上執行得更好;如果您需要區分大小寫,請使用-creplace代替-replace ):

$oldLang = 'EN'
$newLang = 'FR'

$regex = @(
  "(?<prefix>/PartOfPath/)$oldLang(?<suffix>/EndofPath/Caution.txt)",
  "(?<prefix>/OtherPartOfPath/)$oldLang(?<suffix>/EndofPath/Note.txt)",
  "(?<prefix>/ThirdPartOfPath/)$oldLang(?<suffix>/OtherEndofPath/Warning.txt)"
) -join '|'

Get-ChildItem C:\TestFolder\Test.txt -Filter *.txt -Recurse | ForEach-Object {
  ($_ |Get-Content -Raw) -replace $regex, "`${prefix}$newLang`${suffix}" |
    Set-Content -LiteralPath $_.FullName
}
  • 請參閱此 regex101.com 頁面,了解正則表達式的說明以及對其進行試驗的能力。

  • 用作替換操作數的表達式"`${prefix}$newLang`${suffix}"混合了 PowerShell 的預先字符串插值( $newLang ,也可以寫為${newLang} )和引用正則表達式中命名的捕獲組(例如(?<prefix>...) ),只是巧合地使用與 PowerShell 變量相同的符號(盡管需要將名稱括在{...}中;另外,這里是$字符。必須是` -escaped 以防止 PowerShell 的字符串插值解釋它們); 有關背景信息,請參閱此答案

  • 請注意-RawGet-Content的使用,它將一個文本文件作為一個整體讀入 memory,作為單個多行字符串。 鑒於在這種情況下您不需要逐行處理,這大大加快了給定文件的處理速度。

  • 作為一般提示:您可能需要將-Encoding參數與Set-Content一起使用以確保所需的字符編碼,因為 PowerShell 在讀取文件時從不保留文件的原始編碼。 By default, you'll get ANSI-encoded files in Windows PowerShell , and BOM-less UTF-8 files in PowerShell (Core) 7+ .

暫無
暫無

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

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