Replace only digit in a specific line of text file

Viewed 68

I have a text file with unique IPs like this

172.21.2.15|3
172.33.3.45|6
172.15.12.5|2

I need to find a specific row based on IP and then replace the digit after the delimiter adding one to the current value.

By now I was just able to find the row in this way

$client = "172.33.3.45"
$line = gc C:\myfile.txt | select-string $client | Select-Object -ExpandProperty Line

but I don't know how to do the replace even though I have already made several searches.

How can I add 1 to the digit for this IP in the file?

3 Answers

try this :

$IPToFind='172.33.3.45'
$File=C:\myfile.txt

$Contentcsv=import-csv $File -Delimiter '|' -Header IP, ID
$Contentcsv | %{if($_.IP -eq $IPToFind){$_.ID=[int]$_.ID+1}; "{0}|{1}" -f $_.IP, $_.ID} | Out-File $File

If you want more explanation :

$IPToFind='172.33.3.45'

$Contentcsv=import-csv "C:\temp\test.txt" -Delimiter '|' -Header IP, ID
$Contentcsv | Foreach{

    #modify value if IP is founded
    if($_.IP -eq $IPToFind)
    {
    $_.ID=[int]$_.ID+1
    }; 

    #send tou output with -f (-format operator)
    "{0}|{1}" -f $_.IP, $_.ID

} | Out-File "C:\temp\test.txt"

Here is alternative method without using any loops:

using namespace System.Text.RegularExpressions

[string] $IP = "172.33.3.45"
$Data = Get-Content $pwd\address.txt -Raw

[regex] $Client = "(?<ip>" + [regex]::Escape($IP) + "\|)(?<digit>\d+)"

$Evaluator = {
    param($Match)

    [string] $Value = $Match.Groups["digit"].Value
    $Match.Groups["ip"].Value + ([System.Int32]::Parse($Value) + 1)
}

[regex]::Replace($Data, $Client, $Evaluator, [RegexOptions]::Multiline) |
Out-File $pwd\updated.txt

Since we are all being creative here, and the OP seems lost on the working helpful answers, as per the op comment...

"Now I try even to understand your code."

...

Here is an alternative method without using any importing, loops, custom formatting, shorthand/aliases, etc.

• Using PSScriptAnalyzer to check your PowerShell code for best practices

http://mikefrobbins.com/2015/11/19/using-psscriptanalyzer-to-check-your-powershell-code-for-best-practices

When your coding/developer tools warn you of errors in your scripts/funciton/modules, etc., (which aliases are considered), then, well, you know.

• Best Practices for aliaes

https://devblogs.microsoft.com/scripting/best-practice-for-using-aliases-in-powershell-scripts

https://devblogs.microsoft.com/scripting/using-powershell-aliases-best-practices

Hey, but it's all about choice.

;-}

As well as, hopefully, in plain English for all skill levels, thus, may be a bit easier to read, understand, no overly cryptic stuff to have to figure out, and to have long term care and feeding, without further explanation, for those who'd see/share it later.

;-}

<# .Synopsis Replace only the digit in a specific line of text file

.DESCRIPTION
   Given a text file with custom formatted IPAddresses. Read the content and 
   increment the last digit in the custom IPAddress

.EXAMPLE
   .\Edit-IPAddressList.ps1

    # Results

    VERBOSE: 
    *** Environment initialization ***


    *** Collecting content for modification ***

    172.21.2.15|3
    172.33.3.45|6
    172.15.12.5|2

    *** Building replacement content ***


    *** Writing replacement content to current file ***

    VERBOSE: Performing the operation "Set Content" on target "Path: D:\Temp\IPList.txt".
    VERBOSE: Performing the operation "Clear Content" on target "Item: D:\Temp\IPList.txt".

    *** Modification results ***

    172.21.2.15|3
    172.33.3.45|7
    172.15.12.5|2



.INPUTS
   Full file path to the IPAddress files

.OUTPUTS
   Updates IPAddress files without the need for new files

.NOTES
   Leveraging nested variables to combine results for specific results per file
   read.

.COMPONENT
   None - stand alone

.ROLE
   File operations. 

.FUNCTIONALITY
   Updating file content specifics for required use cases.
   The regular expressions are used to supply and parse text.

   '\|'          = split the string at the pipe
   '.*Path\s|\}' = remove uneeded string content 
   [1]           = get the array position from a split
   [int          = Setting data type for math needs
#>

Clear-Host

Write-Verbose -Message "`n*** Environment initialization ***`n" -Verbose
$FilePath, 
$SearchString, 
$StringSplit,
$ReplacementPattern = 'D:\Temp\IPList.txt', 
                      '172.33.3.45', 
                      '\|', 
                      '.*Path\s|\}'

Write-Host "`n*** Collecting content for modification ***`n" -ForegroundColor Yellow

Get-Content -Path $FilePath

Write-Host "`n*** Building replacement content ***`n" -ForegroundColor Yellow

$ReplacementContent = ((($FindSearchString = (Get-Content -Path $FilePath) -match $SearchString) -Split $StringSplit)[1]), 
                      ([int](($FindSearchString -Split $StringSplit)[1]) + 1)

Write-Host "`n*** Writing replacement content to current file ***`n" -ForegroundColor Yellow

(Get-Content -Path $FilePath) -replace $ReplacementContent | 
Set-Content -Path ($FilePath -replace $ReplacementPattern) -Verbose

Write-Host "`n*** Modification results ***`n" -ForegroundColor Yellow

Get-Content -Path $FilePath

Note: non of the Write-Host stuff is needed. It's just here for this post and really should be removed.

Neither those Write-Verbose, verbose items and the beginning and ending Get-Content lines.

The comment-based help block is optional, but it's a prudent segment, to avoid code to avoid unneeded comments in code lines.

So, then, just this:

Clear-Host
$FilePath, $SearchString, $StringSplit,
$ReplacementPattern = 'D:\Temp\IPList.txt', '172.33.3.45', '\|', '.*Path\s|\}'

$ReplacementContent = ((($FindSearchString = (Get-Content -Path $FilePath) -match $SearchString) -Split $StringSplit)[1]), 
                      ([int](($FindSearchString -Split $StringSplit)[1]) + 1)

(Get-Content -Path $FilePath) -replace $ReplacementContent | 
Set-Content -Path ($FilePath -replace $ReplacementPattern)
Related