PowerShell脚本:验证参数并判断两IP是否属同一网段
PowerShell脚本:判断两个IP是否同网段(含参数验证)
以下是满足需求的完整脚本,包含参数合法性校验和网段判断逻辑:
<# .SYNOPSIS 判断两个IP地址是否属于同一网段,支持子网掩码的两种输入格式 #> [CmdletBinding()] param( [Parameter(Mandatory = $true, HelpMessage = "输入第一个IP地址,格式如192.168.1.1")] [string]$address_1, [Parameter(Mandatory = $true, HelpMessage = "输入第二个IP地址,格式如192.168.1.100")] [string]$address_2, [Parameter(Mandatory = $true, HelpMessage = "输入子网掩码,支持格式如255.255.255.0或24")] [string]$mask ) # 验证IP地址格式是否合法 function Test-ValidIP { param([string]$ip) # 正则匹配IP格式,同时验证每个段数值在0-255之间 if ($ip -match '^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$') { return ($matches[1] -le 255 -and $matches[1] -ge 0) -and ($matches[2] -le 255 -and $matches[2] -ge 0) -and ($matches[3] -le 255 -and $matches[3] -ge 0) -and ($matches[4] -le 255 -and $matches[4] -ge 0) } return $false } # 验证子网掩码并转换为CIDR前缀长度 function Convert-ToCIDR { param([string]$mask) # 情况1:输入是数字格式(如8、24) if ($mask -match '^\d{1,2}$') { $cidr = [int]$mask if ($cidr -ge 0 -and $cidr -le 32) { return $cidr } else { throw "子网掩码数字格式非法,必须在0-32之间" } } # 情况2:输入是点分十进制格式(如255.255.255.0) elseif ($mask -match '^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$') { # 先验证每个段的合法性 if (!(([int]$matches[1] -le 255 -and [int]$matches[1] -ge 0) -and ([int]$matches[2] -le 255 -and [int]$matches[2] -ge 0) -and ([int]$matches[3] -le 255 -and [int]$matches[3] -ge 0) -and ([int]$matches[4] -le 255 -and [int]$matches[4] -ge 0))) { throw "子网掩码点分十进制格式非法" } # 将掩码转换为二进制字符串,统计连续的1的数量(即CIDR长度) $binaryMask = ($matches[1..4] | ForEach-Object { [Convert]::ToString([int]$_, 2).PadLeft(8, '0') }) -join '' # 验证是否是合法子网掩码(二进制必须是连续的1后跟连续的0) if ($binaryMask -notmatch '^1*0*$') { throw "输入的不是合法的子网掩码" } return ($binaryMask -replace '0', '').Length } else { throw "子网掩码格式非法,仅支持点分十进制(如255.255.255.0)或数字(如24)格式" } } # 计算IP地址对应的网络地址 function Get-NetworkAddress { param( [string]$ip, [int]$cidr ) $ipBytes = [System.Net.IPAddress]::Parse($ip).GetAddressBytes() $maskBytes = [System.Net.IPAddress]::Parse(([System.Net.IPAddress]::NetworkToHostOrder([System.BitConverter]::ToInt32(([System.Net.IPAddress]::Parse("255.255.255.255").GetAddressBytes()), 0)) -band ([System.Math]::Pow(2, 32) - [System.Math]::Pow(2, 32 - $cidr)))).GetAddressBytes() [Array]::Reverse($ipBytes) [Array]::Reverse($maskBytes) $networkInt = [System.BitConverter]::ToUInt32($ipBytes, 0) -band [System.BitConverter]::ToUInt32($maskBytes, 0) $networkBytes = [System.BitConverter]::GetBytes($networkInt) [Array]::Reverse($networkBytes) return [System.Net.IPAddress]$networkBytes } # 执行参数验证 if (!(Test-ValidIP $address_1)) { Write-Error "address_1不是合法的IP地址格式" exit 1 } if (!(Test-ValidIP $address_2)) { Write-Error "address_2不是合法的IP地址格式" exit 1 } try { $cidr = Convert-ToCIDR $mask } catch { Write-Error $_.Exception.Message exit 1 } # 计算两个IP的网络地址 $network1 = Get-NetworkAddress $address_1 $cidr $network2 = Get-NetworkAddress $address_2 $cidr # 判断并输出结果 if ($network1 -eq $network2) { Write-Output "yes" } else { Write-Output "no" }
关键部分说明:
- 参数定义:通过
[CmdletBinding()]和param块声明三个必填参数,每个参数都添加了帮助信息,方便用户使用-?查看说明。 - IP合法性验证:
Test-ValidIP函数用正则匹配IP格式,并检查每个段的数值范围在0-255之间,确保输入是有效的IPv4地址。 - 子网掩码处理:
Convert-ToCIDR函数处理两种输入格式:- 数字格式:验证是否在0-32之间,直接返回作为CIDR长度。
- 点分十进制格式:先验证格式合法性,再转换为二进制字符串,检查是否是连续的1后跟连续的0(合法子网掩码的特征),最后统计1的数量得到CIDR长度。
- 网络地址计算:
Get-NetworkAddress函数将IP和CIDR转换为网络地址,通过字节运算实现掩码与IP的按位与操作,得到网络地址。 - 结果判断:比较两个IP对应的网络地址,相同则输出
yes,否则输出no。
使用示例:
# 合法参数示例,输出yes .\Check-SameNetwork.ps1 -address_1 192.168.1.5 -address_2 192.168.1.20 -mask 24 # 合法参数示例,输出no .\Check-SameNetwork.ps1 -address_1 192.168.1.5 -address_2 192.168.2.20 -mask 255.255.255.0 # 非法IP参数示例,报错 .\Check-SameNetwork.ps1 -address_1 192.168.1.256 -address_2 192.168.1.20 -mask 24
内容的提问来源于stack exchange,提问作者Art
相关产品推荐
相关产品推荐

