Home > front end >  Powershell scripting - replace text in files
Powershell scripting - replace text in files

Time:09-21

Given these powershell functions below. I'm trying to replace the version text with another version that I specify. All my paths are correct, and I output both the current version and new version appropriatlely. When i go to replace them, the file indicates that it has changed, but no text was changed.

Alternately, I've found if i specify the exact current version as a string variable and bypass the Get-VersionXXX calls, it replaces the version without issues. Is there anything obvious I'm doing wrong?

function Get-VersionAndDateFromFile([string] $versionFile, [string] $versionString)
{
    if (-Not(Test-Path -path $versionFile))
    {
        return ""
    }
    else
    {
        #foreach($line in [System.IO.File]::ReadLines($versionFile))
        (Get-Content -Path $versionFile -Raw) | ForEach-Object {
            $line = $_
            if ($line.Contains($versionString))
            {
                if ($line.Contains(""""))
                {
                    $tokens = $line.Split('\"')
                    return $tokens[1]
                }
            }
        }
    }

    return ""
}

function Get-VersionOnlyFromFile([string] $versionFile, [string] $versionString)
{
    [string] $versionAndDate = Get-VersionAndDateFromFile $versionFile $versionStriong
    return VersionFromVersionAndDateString $versionAndDate
}

function Get-VersionFromVersionAndDateString([string] $versionAndDateString)
{
    if (!$versionAndDateString)
    {
        return ""
    }
    else
    {
        if ($versionAndDateString.Contains(" "))
        {
            $newTokens = $versionAndDateString.Trim().Split(" ")          
            return $newTokens[0]
        }
        else
        {
            return $versionAndDateString
        }
    }
}

function ReplaceTextInFile([string] $fullPath, [string] $oldString, [string] $newString)
{
    Write-Host "Old " $oldString
    Write-Host "New " $newString
    ((Get-Content -path $fullPath -Raw) -replace $oldString,$newString) | Set-Content -Path $fullPath
}

Calling code:

[string] $newVersionString = "1.2.3.4.6   09-16-2021"
[string] $currentVersionString = Get-VersionAndDateFromFile $pathToVersionFile "SW_VERSION"
ReplaceTextInFile -fullPath $pathToVersionFile -oldString $currentVersionString -newString $newVersionString

finally: file is a header file called Version.h

#define SW_VERSION "1.2.3.4.5 09-14-2021"

CodePudding user response:

Unless explicitly redirected all output in a function is returned to the pipeline. The return command is redundant. As such, you're sending back two things in your function, first is the version number and second is an empty string (lines starting with >>>):

function Get-VersionAndDateFromFile([string] $versionFile, [string] $versionString)
{
    if (-Not(Test-Path -path $versionFile))
    {
        return ""
    }
    else
    {
        #foreach($line in [System.IO.File]::ReadLines($versionFile))
        (Get-Content -Path $versionFile -Raw) | ForEach-Object {
            $line = $_
            if ($line.Contains($versionString))
            {
                if ($line.Contains(""""))
                {
                    $tokens = $line.Split('\"')
>>>                 return $tokens[1]
                }
            }
        }
    }

>>> return ""
}

You convert the output to a string, and by all accounts it looks right, but if you look more closely you'll see there's a space after the date:

PS C:\WINDOWS\system32> ">$currentVersionString<"
>1.2.3.4.5 09-14-2021 <

If we comment out the last return in that function the space goes away, and your replace should work fine.

function Get-VersionAndDateFromFile([string] $versionFile, [string] $versionString)
{
    if (-Not(Test-Path -path $versionFile))
    {
        return ""
    }
    else
    {
        #foreach($line in [System.IO.File]::ReadLines($versionFile))
        (Get-Content -Path $versionFile -Raw) | ForEach-Object {
            $line = $_
            if ($line.Contains($versionString))
            {
                if ($line.Contains(""""))
                {
                    $tokens = $line.Split('\"')
                    return $tokens[1]
                }
            }
        }
    }

#    return ""
}

To be honest, it would be much simpler to do this:

function Get-VersionAndDateFromFile([string] $versionFile, [string] $versionString)
{
    if (Test-Path -path $versionFile)
    {
        Get-Content -Path $versionFile -Raw | Where-Object{$_ -match "$versionString\s ""(. ?)"""} | ForEach-Object {
            $Matches[1]
        }
    }
}

CodePudding user response:

Run your Replace Function with these 2 added lines, as shown below...

$old = $oldString -replace '\s','\s'; $old = $old -replace '\s$';

You'll find you're capturing an extra space at the end of your OldString variable. Like so: 1.2.3.4.5\s\s09-16-2021\s

The two lines fix the issue and it does the replace... or you can fix your Get-Version function to capture the correct string.

function ReplaceTextInFile([string] $fullPath, [string] $oldString, [string] $newString) { Write-Host "Old " $oldString Write-Host "New " $newString

$old = $oldString -replace '\s','\s'; #replaces space with \s
$old = $old -replace '\\s$'; #removes trailing space at end of line

$old = $oldString -replace '\s','\s'; $old = $old -replace '\\s$'
((Get-Content -path $fullPath -Raw) -replace $old,$newString) | Set-Content -Path $fullPath 

}

  • Related