1

I'm currently writing a PowerShell script to help out a user.

I am reading a file which is generated by a program into an array.

I iterate through it with a foreach and make changes to it as necessary.

Then I want to write the text, including changes, into a new file.

Param(
    [Parameter(Mandatory=$true, Position=0, HelpMessage="pulse?")]
    [string]$pulse,

    [Parameter(Mandatory=$true, Position=1, HelpMessage="milimeter?")]
    [string]$milimeter
)

$textfile = Get-Content C:\11111_O.jbi

foreach($string in $textfile) {

    $string -match '(EC\d*=)'

    if($matches) {
        [string]$regex = $matches[1]
        [string]$replacement = ($regex + $pulse + ',')
        $string = $string -replace '(EC\d*=)', "$replacement"
    }
}

$textfile | Out-File -FilePath C:\new_file.jbi

But even though i have checked the code inside the foreach multiple times (it does what it's supposed to do to $string). The output of $textfile always stays the same.

How can I get $textfile to update and reflect the changes I want to do to it in my foreach?

3 Answers 3

5

Because you're using foreach, you get a copy of each line into the $string variable - that is what you modify on each iteration, so the contents of $textfile itself are never changed.

You can just use a for loop instead:

for ($i = 0; $i -lt $textfile.count; $i++) {
  $textfile[$i] -match '(EC\d*=)'
  if($matches) {
    [string]$regex = $matches[1]
    [string]$replacement = ($regex + $pulse + ',')
    $textfile[$i] = $textfile[$i] -replace '(EC\d*=)', "$replacement"
  }
}

$textfile | out-file -filepath C:\new_file.jbi
Sign up to request clarification or add additional context in comments.

Comments

2

The $string variable in the foreach statement refers to the "current" item in the collection, but it's a copy, not a reference to the original collection.

You should make a new array or make it a pipeline with the ForEach-Object cmdlet:

$textfile | ForEach-Object -Process {
    $string = $_
    if($string -match '(EC\d*=)')
    { 
        [string]$regex = $matches[1]
        [string]$replacement = ($regex + $pulse + ',')
        $string = $string -replace '(EC\d*=)', "$replacement"
    }
    $string    
} | out-file -filepath C:\new_file.jbi

Your regex stuff is also unnecessarily complex. You can just do the replace, using a backreference to refer to the matched part, so the whole thing can be further simplified to this:

$textfile | ForEach-Object -Process {
    $_ -replace '(EC\d*=)', "`${1}$pulse,"
} | out-file -filepath C:\new_file.jbi

Having done that, you no longer need ForEach-Object because -replace can work on arrays:

$textfile -replace '(EC\d*=)', "`${1}$pulse," | 
   out-file -filepath C:\new_file.jbi

6 Comments

I can't get that second example to work. I can get -replace '(EC\d*=)', "`$1$pulse," to work, but it fails if $pulse starts with a digit. Also, I think you need an -append on that Out-File, or trade it for Add-Content.
@mjolinor you're right, I updated the code so it works correctly with the backreference, but I don't think you'd want to append in this case. The output of the ForEach-Object call will all be piped into Out-File, so it will contain the full content, unless I'm missing something.
You're right about the -append, but I'd still consider that replace potentially buggy. Also, the Foreach isn't really necessary. -Replace will work as an array operator.
@mjolinor true, -replace as array operator is even better, but why would the replace be buggy?
As I said earlier, it seems to fail if $pulse starts with a digit. I think that confuses the parsing of the backreference.
|
0

If you really need to update $textfile in place you would need to use a for loop, however if you are just outputting to a file there is no need to manipulate the array, you can just dump the manipulated contents straight to the file.

foreach($string in $textfile) {
  $string -match '(EC\d*=)'
  if($matches) { 
    [string]$regex = $matches[1]
    [string]$replacement = ($regex + $pulse + ',')
    $string -replace '(EC\d*=)', "$replacement"
  }
} | out-file -filepath C:\new_file.jbi

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.