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
)