简体   繁体   中英

Change 3rd octet of IP in string format using PowerShell

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.

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

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://docs.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 .

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, ie 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 .

For complete your method but shortly :

$a,$b,$c,$d = "192.168.13.1".Split(".")
$IP="$a.$b.$([int]$c+1).$d"
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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM