Home > OS >  Powershell overwriting file contents with match instead of editing single line
Powershell overwriting file contents with match instead of editing single line

Time:12-15

I have a text file that contains a string I want to modify.

Example text file contents:

abc=1
def=2
ghi=3

If I run this code:

$file =  "c:\test.txt"
$MinX = 100
$MinY = 100

$a = (Get-Content $file) | %{
    if($_ -match "def=(\d*)"){
        if($Matches[1] -gt $MinX){$_ -replace "$($Matches[1])","$($MinX)" }
    }
}
$a

The result is:

def=100

If I omit the greater-than check like so:

$a = (Get-Content $file) | %{
    if($_ -match "def=(\d*)"){
        $_ -replace "$($Matches[1])","$($MinX)"
    }
}
$a

The result is correct:

abc=1
def=100
ghi=3

I don't understand how a simple integer comparison before doing the replace could screw things up so badly, can anyone advise what I'm missing?

CodePudding user response:

That's because the expression ($Matches[1] -gt $MinX) is a string comparison. In Powershell, the left-hand side of a comparison dictates the comparison type and since that is of type [string], Powershell has to cast/convert the right-hand side of the expression to [string] also. You expression, therefore, is evaluated as ([string]$Matches[1] -gt [string]$MinX).

CodePudding user response:

The comparison operator -gt will never get you a value of $true because you need to

  • cast the $matches[1] string value to int first so it compares two integer numbers
  • 2 is never greater than 100.. Change the operator to -lt instead.
  • Your code outputs only one line, because you forgot to also output unchanged lines that do not match the regex
$file = 'c:\test.txt'
$MinX = 100
$MinY = 100

$a = (Get-Content $file) | ForEach-Object {
    if ($_ -match '^def=(\d )'){
        if([int]$matches[1] -lt $MinX){ $_ -replace $matches[1],$MinX }
    }
    else {
        $_
    }
}

$a

Or use switch (is also faster than using Get-Content):

$file = 'c:\test.txt'
$MinX = 100
$MinY = 100

$a = switch -Regex -File $file {
    '^def=(\d )' { 
        if([int]$matches[1] -lt $MinX){ $_ -replace $matches[1],$MinX }
    }
    default { $_ }
}

$a

Output:

abc=1
def=100
ghi=3
  • Related