0

What if some file contains strings like

11111111111111
22222222222222
33333333333333
44444444444444
22222222222222
33333333333333
22222222222222
11111111111111

and I need to find and replace 22222222222222 to 777777777777777 just 2 times while processing the file string by string using foreach and save file with changes after that.

$file = 'path_to\somefile.txt'
foreach($string in $file) 
{
   $new_string = $string -replace '22222222222222', '777777777777777'
}
$string | Out-file $file

I understand that the script above will replace all strings and will be saved just with one string instead of my requirements.

Aatif Akhter
  • 2,126
  • 1
  • 25
  • 46
  • 1
    Use a in the loop counter to keep track of the number of times the string is found, and exit the script when the count is reached. – postanote Apr 13 '20 at 22:22
  • Does this answer your question? [Replacing only the first occurrence of a word in a string](https://stackoverflow.com/questions/40089631/replacing-only-the-first-occurrence-of-a-word-in-a-string) – OwlsSleeping Apr 13 '20 at 23:01

1 Answers1

0

As per the comment, one needs to keep track how many replacements are done.

To read a file line by line, use .Net's StreamReader.ReadLine(). In a while loop, keep reading until you are at end of file.

While reading lines, there are a few things. Keep track how many times the replaceable string is encountered, and, if need be, replace it. The results must be saved in both cases: a line that was replaced and all the other lines too.

It's slow to add content into a file on line by line cases, even on the days of SSDs. A bulk operation is much more efficient. Save the modified data into a StringBuilder. After the whole file is processed, write the contents on a single operation. If the file's going to be large (one gigabyte or more), consider writing 10 000 rows a time. Like so,

$sb = New-Object Text.StringBuilder
$reader = [IO.File]::OpenText("MyFile.csv")
$found = 0
$oldVal = '22222222222222'
$newVal = '777777777777777'

# Read the file line by line
while($null -ne ($line = $reader.ReadLine())) {

    # Only change two first occurrances
    if( ($found -lt 2) -and ($line -eq $oldVal) ) {
        ++$found
        $line = $newVal
    }

    # Add data into a buffer
    [void]$sb.AppendLine($line)
}

add-content "SomeOtherFile.csv" $sb.ToString()
$reader.close()
vonPryz
  • 22,996
  • 7
  • 54
  • 65