Powershell-根据索引匹配拆分和替换

Powershell- match split and replace based on index

我有一个文件

AB*00*Name1First*Name1Last*test
BC*JCB*P1*Church St*Texas
CD*02*83*XY*Fax*LM*KY
EF*12*Code1*TX*1234*RJ

我需要在文件夹中的每个文件中单独将 CD 段中的第 5 个元素从 LM 替换为 ET。元素分隔符是*,如上述示例文件内容中所述。我是 PowerShell 的新手并尝试了如下代码,但不幸的是它没有给出预期的结果。你们中的任何人都可以提供一些帮助吗?

foreach($xfile in $inputfolder)
{
If ($_ match "^CD\*")
{
[System.IO.File]::ReadAllText($xfile).replace(($_.split("*")[5],"ET") | Set-Content $xfile
}
[System.IO.File]::WriteAllText($xfile),((Get-Content $xfile -join("~")))
}

你可以捕捉到第1组比赛前的一切,然后匹配LM。

在替换中使用ET

^(CD*(?:[^*\r\n]+\*){5})LM\b

Regex demo

如果您不想从字面上匹配 LM,您还可以匹配除 * 或换行符之外的任何其他字符。

^(CD*(?:[^*\r\n]+\*){5})[^*\r\n]+\b

替换示例

$allText = Get-Content -Raw file.txt
$allText -replace '(?m)^(CD*(?:[^*\r\n]+\*){5})LM\b','ET'

输出

AB*00*Name1First*Name1Last*test
BC*JCB*P1*Church St*Texas
CD*02*83*XY*Fax*ET*KY
EF*12*Code1*TX*1234*RJ

这里有一种略微不同的方式......[grin]它的作用......

  • 在测试文件中伪造读数
    当准备好真正做到这一点时,删除整个 #region/#endregion 块并使用 Get-Content
  • 设置常量
  • 遍历导入的文本文件行
  • 检查以目标模式开头的行
  • 如果找到...
    == 使用 [regex]::Escape() 转义旧值以处理星号
    == 用新值替换转义的旧值
    == 输出该行的新版本
  • 如果未找到,则按原样输出行
  • 将所有行存储到 $OutStuff var
  • 在屏幕上显示

代码...

#region >>> fake reading in a plain text file
#    in real life, use Get-Content
$InStuff = @'
AB*00*Name1First*Name1Last*test
BC*JCB*P1*Church St*Texas
CD*02*83*XY*Fax*LM*KY
EF*12*Code1*TX*1234*RJ
'@ -split [System.Environment]::NewLine
#endregion >>> fake reading in a plain text file

$TargetLineStart = 'CD*'
$OldValue = '*LM*'
$NewValue = '*ET*'
$OutStuff = foreach ($IS_Item in $InStuff)
    {
    if ($IS_Item.StartsWith($TargetLineStart))
        {
        $IS_Item -replace [regex]::Escape($OldValue), $NewValue
        }
        else
        {
        $IS_Item
        }
    }

$OutStuff

输出...

AB*00*Name1First*Name1Last*test
BC*JCB*P1*Church St*Texas
CD*02*83*XY*Fax*ET*KY
EF*12*Code1*TX*1234*RJ

我会将其保存到新文件[或覆盖旧文件]给用户。 [咧嘴一笑]