使用 Lookuptable 和 Switch 替换大文件中的许多字符串

问题描述 投票:0回答:1

我不精通编码。在这里找到了解决方案:使用 ForEach-Object 扫描日志文件并替换文本需要很长时间

但是,当查找表中的字符串包含括号(或)时,会遇到错误。

非常感谢任何帮助。

    $lookupTable = @{
        "Hello (1234)" = "new string 1"
        "Some'thing (2023)" = "other"
    }
    
    $inputfile = "c:\somewhere\*.*"
    
    Get-ChildItem $inputfile -Filter *.txt | ForEach-Object {
        $outfile = Join-Path -Path "c:\else\" -ChildPath ('{0}{1}_new' -f $_BaseName, $_.Extension)
        $regexLookup = '({0})' -f (($lookupTable.Keys | ForEach-Object { [regex]::escape($_) }) -join '|')
        $writer = [System.IO.StreamWriter]::new($outfile, $true)
   
        Switch -regex -file $_ {
            $regexLookup {
                $line = $_
                $match = [regex]::Match($line, $regexLookup)
                while ($match.Success) {
                    $line = $line -replace $match.Value, $lookupTable[[regex]::Unescape($match.Value)]
                    $match = $match.NextMatch()
                }
            $writer.WriteLine($line)
            }
        default { $write.Writeline($_) }
        }
    $writer.flush()
    $writer.Dispose()
    }

我得到的错误是:

正则表达式模式 Hello (1234) 无效。

在 c:\wheremyfileis.ps1:....

  • $line = $line - 替换 $match.Value, $lookupTable[[正则表达式 ...
powershell performance replace
1个回答
0
投票

出现您遇到的问题是因为括号是正则表达式中的特殊字符。当它们出现在您的查找键中时,它们将被解释为搜索模式的一部分,从而导致错误。

您已经在脚本中使用了

[regex]::escape($_)
,它应该转义正则表达式中的特殊字符,但这似乎不起作用。我对您的代码做了一些调整,现在它在我的机器上按预期工作:

$lookupTable = @{
  "Hello (1234)" = "new string 1"
  "Some'thing (2023)" = "other"
}

$inputfile = "c:\somewhere\*.*"

Get-ChildItem $inputfile -Filter *.txt | ForEach-Object {
  $outfile = Join-Path -Path "c:\else\" -ChildPath ('{0}_new{1}' -f $_.BaseName, $_.Extension)
  $regexLookup = '({0})' -f (($lookupTable.Keys | ForEach-Object { [regex]::escape($_) }) -join '|')
  $writer = [System.IO.StreamWriter]::new($outfile, $true)

  Switch -regex -file $_ {
    $regexLookup {
      $line = $_
      $match = [regex]::Match($line, $regexLookup)
      while ($match.Success) {
        $escapedMatch = [regex]::Escape($match.Value)
        $line = $line -replace $escapedMatch, $lookupTable[$match.Value]
        $match = $match.NextMatch()
      }
      $writer.WriteLine($line)
    }
    default { $writer.Writeline($_) }
  }

  $writer.flush()
  $writer.Dispose()
}

我调整了

-replace
操作以使用
$match.Value
的转义版本,以确保正确处理匹配中的任何特殊字符,并确保用于在
$lookupTable
中查找替换字符串的键是未转义的匹配值。最后,我更改了您的代码,使文件扩展名保持不变,并在最后一个句点之前附加
_new

© www.soinside.com 2019 - 2024. All rights reserved.