Reputation: 82
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
Upvotes: 3
Views: 22834
Reputation: 200373
Your code is unnecessarily convoluted and doesn't make proper use of the features PowerShell provides.
$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}
.$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.`t
). No need to define a variable with a value of [char]9
."$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
)
Upvotes: 8
Reputation: 4669
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
Upvotes: 3