我在Windows 10中使用一些简单的PowerShell代码就有这个奇怪的问题。我认为这可能是我做错了但我不是一个PowerShell天才。
我有这个:
$ix = [System.Net.Dns]::GetHostEntry('<some server with a range of multiple IP addresses here>).AddressList.IPAddressToString;
$e = If ($ix -ne $null) {$ix | % { $_.split('.')[0..1] -join '.'} | % {$_ + '.'}} ;
$r = Get-NetRoute | ? AddressFamily -eq 'IPv4' | Select -exp 'DestinationPrefix'; ForEach ($e in $e) {$xline = $r -match $e}; write $xline
$ ix是从服务器返回到列表的一系列IP地址,然后用于获取$ e。
$ e是从IP地址列表派生的每个IP地址的前两个八位字节的列表。
$ r是路由表IPv4地址
目的是将$ e中IP地址的前两个八位字节与$ r中IP地址的前两个八位字节进行匹配,然后使用$ xline返回匹配的$ r路由表IP地址。这是按预期工作,直到它不再存在。
问题是它会工作正常,然后突然不再工作,因为$ xline出现空,即使$ ix,$ e和$ r值仍然填充且其相关代码工作正常。经过多次尝试后,它将再次开始工作几次,然后停止工作。我不知道我做错了什么,或者这是否是正确的方法,但我喜欢它相对简单。任何帮助,将不胜感激。谢谢。
答案 0 :(得分:1)
试试这个(我重新格式化了一些代码,以便更清楚地进行故障排除):
$ix = [System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).AddressList.IPAddressToString;
$e = If ($ix -ne $null) {
$ix | ForEach-Object { ( $_.split('.')[0..1] -join '.') + '.' }
}
$r = Get-NetRoute | Where-Object { $_.AddressFamily -eq 'IPv4' } | Select-Object -ExpandProperty 'DestinationPrefix'
$xline = ForEach ($f in $e) {
$r -match $f
}
$xline
主要变化是$line
被设置为ForEach
循环中返回的所有值,而不是最后一个。
我还拿出了一个不必要的ForEach-Object
,因为你可以做到它在前一个中所取得的成就。
以下是您的短格式修补程序:
$ix = [System.Net.Dns]::GetHostEntry('<some server with a range of multiple IP addresses here>').AddressList.IPAddressToString;
$e = If ($ix -ne $null) {$ix | % { ($_.split('.')[0..1] -join '.') + '.'} ;
$r = Get-NetRoute | ? AddressFamily -eq 'IPv4' | Select -exp 'DestinationPrefix'; $xline = ForEach ($e in $e) { $r -match $e}; write $xline
答案 1 :(得分:0)
使用一些背景信息补充Mark Wragg's helpful answer :
由于$r
中的$r -match $e
是数组,-match
会执行过滤器:而不是返回布尔,与标量 LHS一样,$r
中的匹配元素自身作为数组返回
@('aa', 'ab', 'bb') -match 'a'
产生@('aa', 'ab')
(而'aa' -match 'a'
- 由于标量 LHS - 产生$True
以表示成功匹配。< / LI>
$r
的元素没有匹配,则会得到空数组(@()
),这在许多PowerShell上下文中似乎是“空”结果或“没有” ” 正如Mark指出的那样,在foreach ($v in $e) {$xline = $r -match $v}; write $xline
循环中(我已使用$e
替换迭代变量$v
以避免混淆),您可以指定$xline
在每次迭代中而不是收集所有结果。
因此,您只使用返回的 last -match
操作 - 这可能是也可能不是空数组,这将是解释断断续续的“不工作”。
正如Mark的代码所暗示的那样,你不需要辅助。 foreach
循环中的变量,因为整个循环可以用作表达式,这意味着它的累积输出是按原样输出(例如,可以在变量中捕获)。
foreach ($v in $e) { $r -match $v }
就是你所需要的。这是一个简化(明确)迭代的简化解决方案(并且可能性能更好,但这不太重要):
# Get all IPv4 destination prefixes.
# Note the use of @(...) around the command, which ensures that its output
# is treated as an *array* (which it most likely is anyway, in this case).
$ip4routeDests = @(Get-NetRoute |
Where-Object AddressFamily -eq IPv4 |
Select-Object -ExpandProperty DestinationPrefix)
# Get the first 2 octets of all IPv4 addresses followed by a `*` to form
# a wildcard expression used with `switch` below.
# IPv4 addresses are identified by the presence of a `.` in them (`-match '\.')
# Regex '^(.+?\..+?\.).*' matches the entire input while extracting only
# the first 2 octets; e.g., '172.16.'
$ip4addrWildcards =
[System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).AddressList.IPAddressToString `
-match '\.' -replace '^(.+?\..+?\.).*', '$1*' #`
# `switch` allows us to implicitly loop over all wildcard patterns and match
# the destination prefixes against each with `-like`.
# This directly outputs all matches, but note that they'll be in the order
# implied by $ip4addrWildcards, i.e., the order in which the wildcards are specified.
switch ($ip4addrWildcards) { default { $ip4routeDests -like $_ } }