Regex IF condition

13,711

Solution 1

Your code is unnecessarily convoluted and doesn't make proper use of the features PowerShell provides.

  • Don't assign $args[...] to parameters. That's not how parameter handling in PowerShell works. Make the parameters mandatory instead.
  • % {if ($_ -notmatch $Match) {$_}} is better phrased as Where-Object {$_ -notmatch $Match}.
  • If $Match is an FQDN the dots might cause false positives (because they match any character, not just literal dots). Either escape $Match ([regex]::Escape($Match)) or use the -notlike operator instead.
  • PowerShell has an escape sequence for tabs (`t). No need to define a variable with a value of [char]9.
  • Putting variables in a double-quoted string ("$var1$var2") is often more readable than string concatenation ($var1 + $var2).

Change your code to something like this:

[CmdletBinding()]
Param(
  [Parameter(Mandatory=$true)]
  [string]$Hostname,
  [Parameter(Mandatory=$true)]
  [string]$IPAddress
)

$SourceFile = 'hosts'

(Get-Content $SourceFile) |
  Where-Object { $_ -notlike "*$Hostname*" } |
  Set-Content $SourceFile

Start-Sleep -Seconds 1

if ($IPAddress -match '^(10|172)\.') {
  "$IPAddress`t$Hostname" | Add-Content $SourceFile
}

If you want to avoid writing the output file multiple times, you could collect the data read in a variable, and then write that variable and the new record in one go:

$hosts = @(Get-Content $SourceFile) | Where-Object { $_ -notlike "*$Hostname*" })

if ($IPAddress -match '^(10|172)\.') {
  $hosts += "$IPAddress`t$Hostname"
}

$hosts | Set-Content $SourceFile

You could further optimize your script by doing the check via parameter validation, so you don't need an if condition in the function body in the first place, e.g. like this:

Param(
  [Parameter(Mandatory=$true)]
  [string]$Hostname,
  [Parameter(Mandatory=$true)]
  [ValidatePattern('^(10|172)\.')]
  [string]$IPAddress
)

or like this:

Param(
  [Parameter(Mandatory=$true)]
  [string]$Hostname,
  [Parameter(Mandatory=$true)]
  [ValidateScript({$_ -match '^(10|172)\.' -and [bool][ipaddress]$_})]
  [string]$IPAddress
)

Solution 2

Some of the comments above use regex to validate the entire IPv4 address. If you are confident that the IP address you are checking is valid, then you can use "^(10|172)\." to verify just the first octet of the address as per your question:

if($newIP -match "^(10|172)\.") { ... }

If you do want to validate the whole address, there is an alternative way to do this by converting $newIP to a [System.Net.IPAddress] type. If this fails the result will be nothing (null), which is implicitly false, so the following gives you a true/false check that a string is a valid IP address:

[bool]($newIP -as [System.Net.IPAddress])

You could use this to validate the input to the function written by Ansgar:

[Parameter(Mandatory=$true)]
[ValidateScript({[bool]($_ -as [System.Net.IPAddress]})
[string]$IPAddress
Share:
13,711
olizimmermann
Author by

olizimmermann

Updated on June 28, 2022

Comments

  • olizimmermann
    olizimmermann almost 2 years

    I'm looking for a way to filter new IP-Addresses in my host file. I created a script which updates my host file every time when I call it with data from the matrix enterprise manager. It works fine. But I have to find a solution that only 10.XX.XX.XX or 172.XX.XX.XX addresses are allowed to update.

    Param(
      $newHost = $args[0],
      $newIP = $args[1]
    )
    
    $SourceFile = "hosts"
    $Match = "$newHost"
    
    (Get-Content $SourceFile) | % {if ($_ -notmatch $Match) {$_}} | Set-Content $SourceFile
    
    Start-Sleep -Seconds 1
    
    $tab = [char]9
    $enter = $newIP + $tab + $newHost
    
    if ($newIP XXXX)  #--> here should be a regex if condition... no clue how it works..
    
    $enter | Add-Content -Path hosts
    
  • Charlie Joynt
    Charlie Joynt almost 7 years
    You're missing a square bracket in the param block before $IPAddress , but I'm not allowed to make a one-character edit. ;-)
  • Ansgar Wiechers
    Ansgar Wiechers almost 7 years
    @CharlieJoynt Thanks for the heads up. Fixed.
  • iRon
    iRon almost 7 years
    Concerning the validation: just[Parameter(Mandatory=$true)][System.Net.IPAddress]$IPAdd‌​ress is better and results in the following standard error when the type is incorrect: Cannot process argument transformation on parameter 'IPAddress'. Cannot convert value "Test" to type "System.Net.IPAddress". Error: "An invalid IP address was specified."
  • Ansgar Wiechers
    Ansgar Wiechers almost 7 years
    In this particular case (since the OP wants to allow only 2 specific /8 subnets, and the address is going to a text file anyway) I would consider a string parameter with a ValidatePattern() clause the better option.
  • Charlie Joynt
    Charlie Joynt almost 7 years
    Ooh. ValidatePattern() is new to me. I think I learn more by answering questions than asking them. :-)