Regex IF condition
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 asWhere-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
olizimmermann
Updated on June 28, 2022Comments
-
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 almost 7 yearsYou're missing a square bracket in the param block before $IPAddress , but I'm not allowed to make a one-character edit. ;-)
-
Ansgar Wiechers almost 7 years@CharlieJoynt Thanks for the heads up. Fixed.
-
iRon almost 7 yearsConcerning the validation: just
[Parameter(Mandatory=$true)][System.Net.IPAddress]$IPAddress
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 almost 7 yearsIn 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 almost 7 yearsOoh.
ValidatePattern()
is new to me. I think I learn more by answering questions than asking them. :-)