【问题标题】:Powershell- match split and replace based on indexPowershell-根据索引匹配拆分和替换
【发布时间】:2020-06-11 03:56:35
【问题描述】:

我有一个文件

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("~")))
}

【问题讨论】:

    标签: powershell replace substring powershell-3.0 powershell-4.0


    【解决方案1】:

    这里有一种稍微不同的方式来到达那里...... [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
    

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

    【讨论】:

    • 谢谢。但是如何在替换一行中的元素后将其保存为原始格式的文件?
    • @ACCADemyACCADemy - 您使用“保存到文件”cmdlet 之一。 [grin] 我会使用$OutStuff | Set-Content -Path $NewFileName
    • @ACCAdemyACCADemy - 不客气!很高兴能帮上忙……[grin]
    【解决方案2】:

    您可以在第 1 组中捕获所有比赛之前的所有内容,然后匹配 LM。

    在替换中使用$1ET

    ^(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','$1ET'
    

    输出

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-09
      • 2014-02-09
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多