You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用LookupTable和Switch替换大文件字符串遇正则错误求助

问题:带括号的字符串替换时触发正则语法错误

我之前找到一个处理大日志文件文本替换的方案,但当LookupTable中的字符串包含括号((或))时,遇到了正则表达式无效的错误。

我的代码如下:

$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()
}

遇到的错误信息:

The regular expression pattern Hello (1234) is not valid.
At c:\wheremyfileis.ps1:....

  • $line = $line -replace $match.Value, $lookupTable[[regex]::Unescape($match.Value)]

解决方案

错误核心:-replace运算符的第一个参数默认按正则表达式解析,而$match.Value里的括号()是正则的特殊分组符号,直接使用会触发语法错误。

修复步骤

  1. 改用字面量替换:用.NET String.Replace()方法替代-replace,该方法会将字符串当作普通文本处理,无需转义特殊字符:

    $line = $line.Replace($match.Value, $lookupTable[$match.Value])
    

    这里不需要[regex]::Unescape($match.Value),因为$match.Value就是原始文本中匹配到的内容,和$lookupTable的键完全一致。

  2. 修正代码笔误:

    • 将$_BaseName改为$_.BaseName(PowerShell属性访问语法错误)
    • 将$write.Writeline($_)改为$writer.WriteLine($_)(变量名拼写错误)

修复后的完整代码

$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[$match.Value])
        $match = $match.NextMatch()
      }
      $writer.WriteLine($line)
    }
    default { $writer.WriteLine($_) }
  }

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

额外优化

如果$lookupTable中的键存在包含关系(比如长键包含短键),可先将键按长度从长到短排序,避免短键先匹配导致长键无法被替换:

$regexLookup = '({0})' -f (($lookupTable.Keys | Sort-Object Length -Descending | ForEach-Object { [regex]::escape($_) }) -join '|')

内容的提问来源于stack exchange,提问作者Linsook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:52:38