powershell替换和删除

时间:2015-01-20 14:49:43

标签: regex powershell

我需要使用标记1234找到字符串====-,然后将####替换为1234,然后删除行====-1234

文本文件可以有一个组(示例文本A):

A;1;1;####;19/01/2015;08:45:58;UNKNOWN;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
====-1234

或多个组(样本文本B):

A;1;1;####;19/01/2015;08:45:58;UNKNOWN;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
====-1234
A;1;1;####;19/01/2015;08:45:58;UNKNOWN;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
====-5678

现在的代码删除了文本文件中的所有内容。有帮助吗?

$regex = 
@'
(?ms)(.+?####;
.+?)
====-(\d+)
'@

Get-Childitem -Path C:\somedir -Filter *.txt |
  foreach {

    $text = Get-Content $_ 

    ([regex]::matches($text,$regex) |
      foreach {
        $_.groups[1].value -replace '####',($_.groups[2].value)
      }) -join '' |
      Set-Content $_.FullName
  }

2 个答案:

答案 0 :(得分:2)

在此方案中,您可能会受益于ArrayList。以下方法迭代文件并记录遇到####====-时的位置。

然后可以通过直接替换找到####的索引处的内容来修改这些位置的内容,其次使用removeAt ArrayList方法删除遇到====-的条目:

[System.Collections.Arraylist]$t = Get-Content .\sampleb.txt
$removeAt = @()

$i = 0
while($i -lt $t.count) {

  if($t[$i] -match "####") {
      $start = $i
  }
  if($t[$i] -match "====-(\d+)") {
      $newval = $t[$start] -replace "####", $matches[1]
      $t[$start] = $newval
      $removeAt += $i
      $start = $i
  }

  $i += 1
}

foreach($idx in ($removeAt | Sort-Object -Descending)) {
    $t.removeAt($idx)
}

$t

输出

A;1;1;1234;19/01/2015;08:45:58;UNKNOWN;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
A;1;1;5678;19/01/2015;08:45:58;UNKNOWN;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;
B;0;0;0;319.95;
B;0;0;0;319.89;

这确实假设您的文件一致且====- 始终跟在####之后,两者是平衡的。否则需要额外的逻辑来解释这一点。

答案 1 :(得分:1)

这似乎是我提供答案的早期问题的延续,但该解决方案依赖于使用Get-Content的-Raw参数,而您显然正在运行V2。除此之外,已发布的数据已从原始问题发生更改,因此无论如何解决方案都无法正常工作。

这是一个更新版本,根据新数据标准调整并与V2兼容:

$regex = 
@'
(?ms)(.+?####;.+?
.+?)
====-(\d+)
'@

$Files = 
Get-Childitem -Path C:\somedir -Filter *.txt 

foreach ($file in $files)
 {
    $Text = Get-Content $file.fullname | out-string 

    ([regex]::matches($text,$regex) |
    foreach {
    $_.groups[1].value -replace '####',($_.groups[2].value)
    }) -join '' |
    Set-Content $file.fullname
 }