4

Think I've found the worst way to do this:

$ip = "192.168.13.1"
$a,$b,$c,$d = $ip.Split(".")
[int]$c = $c
$c = $c+1
[string]$c = $c
$newIP = $a+"."+$b+"."+$c+"."+$d

$newIP

But what is the best way? Has to be string when completed. Not bothered about validating its a legit IP.

0

6 Answers 6

4

Using your example for how you want to modify the third octet, I'd do it pretty much the same way, but I'd compress some of the steps together:

$IP = "192.168.13.1"
$octets = $IP.Split(".")                        # or $octets = $IP -split "\."
$octets[2] = [string]([int]$octets[2] + 1)      # or other manipulation of the third octet
$newIP = $octets -join "."

$newIP
Sign up to request clarification or add additional context in comments.

1 Comment

Really like this and validates mine wasn't total garbage. Didn't realise split would make the array for you so thanks.
2

You can simply use the -replace operator of PowerShell and a look ahead pattern. Look at this script below

Set-StrictMode -Version "2.0"
$ErrorActionPreference="Stop"
cls
$ip1 = "192.168.13.123"
$tests=@("192.168.13.123" , "192.168.13.1" , "192.168.13.12")
foreach($test in $tests)
{
    $patternRegex="\d{1,3}(?=\.\d{1,3}$)"
    $newOctet="420"
    $ipNew=$test -replace $patternRegex,$newOctet
    $msg="OLD ip={0} NEW ip={1}" -f $test,$ipNew
    Write-Host $msg

}

This will produce the following:

OLD ip=192.168.13.123 NEW ip=192.168.420.123
OLD ip=192.168.13.1 NEW ip=192.168.420.1
OLD ip=192.168.13.12 NEW ip=192.168.420.12

How to use the -replace operator?

https://powershell.org/2013/08/regular-expressions-are-a-replaces-best-friend/

Understanding the pattern that I have used

The (?=) in \d{1,3}(?=.\d{1,3}$) means look behind.

The (?=.\d{1,3}$ in \d{1,3}(?=.\d{1,3}$) means anything behind a DOT and 1-3 digits.

The leading \d{1,3} is an instruction to specifically match 1-3 digits

All combined in plain english "Give me 1-3 digits which is behind a period and 1-3 digits located towards the right side boundary of the string"

Look ahead regex

https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference

CORRECTION

The regex pattern is a look ahead and not look behind.

3 Comments

An interesting solution; why are you forcing strict PS2.0 semantics?
(?=\.\d{1,3}$) is a lookahead.
Thanks but this doesn't +1.
1

If you have PowerShell Core (v6.1 or higher), you can combine -replace with a script block-based replacement:

PS> '192.168.13.1' -replace '(?<=^(\d+\.){2})\d+', { 1 + $_.Value }
192.168.14.1
  • Negative look-behind assertion (?<=^(\d+\.){2}) matches everything up to, but not including, the 3rd octet - without considering it part of the overall match to replace.

    • (?<=...) is the look-behind assertion, \d+ matches one or more (+) digits (\d), \. a literal ., and {2} matches the preceding subexpression ((...)) 2 times.
  • \d+ then matches just the 3rd octet; since nothing more is matched, the remainder of the string (. and the 4th octet) is left in place.

  • Inside the replacement script block ({ ... }), $_ refers to the results of the match, in the form of a [MatchInfo] instance; its .Value is the matched string, i.e. the 3rd octet, to which 1 can be added.

    • Data type note: by using 1, an implicit [int], as the LHS, the RHS (the .Value string) is implicitly coerced to [int] (you may choose to use an explicit cast).
      On output, whatever the script block returns is automatically coerced back to a string.

If you must remain compatible with Windows PowerShell, consider Jeff Zeitlin's helpful answer.

2 Comments

I am sorry, I did not understand what you meant when you said "remain compatible" ?
@Sau001 - Windows PowerShell (PowerShell 5 and earlier) does not support a scriptblock for the replacement parameter; as the querent did not specify what version of Powershell he was using, this answer is useful - but with the warning that it won't work with older versions of PowerShell (for which mklement0 pointed to my answer, above). My answer will work on PowerShell Core, but may not be the best answer for PowerShell Core, because of the new capabilities.
1

For complete your method but shortly :

$a,$b,$c,$d = "192.168.13.1".Split(".")
$IP="$a.$b.$([int]$c+1).$d"

1 Comment

Yep, better than mine
0
function Replace-3rdOctet {
    Param(
        [string]$GivenIP,
        [string]$New3rdOctet
    )
    $GivenIP -match '(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})' | Out-Null
    $Output = "$($matches[1]).$($matches[2]).$New3rdOctet.$($matches[4])"
    Return $Output
}

Copy to a ps1 file and dot source it from command line, then type

Replace-3rdOctet -GivenIP '100.201.190.150' -New3rdOctet '42'

Output: 100.201.42.150

From there you could add extra error handling etc for random input etc.

1 Comment

It's not an explicitly stated requirement, but it's what the OP's own code does; either way, I agree that your answer shouldn't have been down-voted, certainly not without feedback - I get that that's frustrating.
0

here's a slightly different method. [grin] i managed to not notice the answer by JeffZeitlin until after i finished this.

[edit - thanks to JeffZeitlin for reminding me that the OP wants the final result as a string. oops! [*blush*]]

what it does ...

  • splits the string on the dots
  • puts that into an [int] array & coerces the items into that type
  • increments the item in the targeted slot
  • joins the items back into a string with a dot for the delimiter
  • converts that to an IP address type
  • adds a line to convert the IP address to a string

here's the code ...

$OriginalIPv4 = '1.1.1.1'
$TargetOctet = 3

$OctetList = [int[]]$OriginalIPv4.Split('.')
$OctetList[$TargetOctet - 1]++

$NewIPv4 = [ipaddress]($OctetList -join '.')

$NewIPv4
'=' * 30
$NewIPv4.IPAddressToString

output ...

Address            : 16908545
AddressFamily      : InterNetwork
ScopeId            : 
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 1.1.2.1

==============================
1.1.2.1

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.