1

I need the code to find the string 1234 using the marker ====-, then replace #### with the 1234, then delete the line ====-1234.

The text file can have one group (Sample Text 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

Or multiple groups (Sample Text 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

The code as of right now deletes everything in the text file. Any help?

$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 Answers 2

2

You might benefit from using an ArrayList in this scenario. The following approach iterates over the file and notes the positions when either #### or ====- are encountered.

It can then modify the contents at those positions by firstly directly replacing the contents at the index where #### was found, and secondly by using the removeAt method of ArrayList to delete the entries where ====- was encountered:

[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

Outputs

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;

This does assume your file is consistent and that ====- always follows #### and the two are balanced. Extra logic is otherwise required to account for that.

Sign up to request clarification or add additional context in comments.

2 Comments

great thanks. yes they are always going to be '====-' and '####'. i am creating this txt file and picked those markers. Now i need this to edit multiple files in the same directory and override the file. Possible?
Of course. Different question though so you should really ask a new one and show where you're getting stuck. You'd just need to get all the files, loop over them and run that code for each, and write $t back out to the current file name
1

This appears to be a continuation of an earlier question I had provided an answer to, but that solution relied on using the -Raw parameter of Get-Content and you're apparently running V2. Beyond that the posted data has changed from the original question, so that solution wouldn't have worked anyway.

Here's an updated version, adjusted for the new data criteria and compatible with 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
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.