我现在已经把头撞到墙上好几个小时了,我正在寻求帮助。为了简化我的问题,我有两个数组,一个包含通配符,另一个使用这些通配符:
$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
我无法让PowerShell认识到这些匹配。
我的最终目标是输出一个告诉我,Purple.102和orange.abc不在$ WildCardArray中。
似乎超级简单!我尝试过的一些事情:$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
foreach($Item in $SpelledOutArray)
{
$item | where {$wildcardarray -contains $item}
}
我得到BLUE!.txt,因为它是我的控制,没有通配符。如果我将其更改为-notcontains,我将返回除BLUE之外的所有结果。我尝试过包含,匹配,等于,喜欢和所有对立面,比较对象,没有任何作品。我没有错误,我只是没有得到预期的结果
我尝试更换" *"使用[a-zA-Z]和其他组合,但它从字面上取代它,而不是作为通配符。我不确定我做错了什么...... PSVersion 5.1 Win 10
有没有人知道为什么/匹配/包含不起作用的背后的逻辑,以及我能做些什么让它起作用?它不一定非常漂亮,只需要工作
答案 0 :(得分:3)
您的通配符数组实际上是要查找的模式列表。您可以将其转换为单个正则表达式并与之匹配:
$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
# Turn wildcards into regexes
# First escape all characters that might cause trouble in regexes (leaving out those we care about)
$escaped = $WildcardArray -replace '[ #$()+.[\\^{]','\$&' # list taken from Regex.Escape
# replace wildcards with their regex equivalents
$regexes = $escaped -replace '\*','.*' -replace '\?','.'
# combine them into one regex
$singleRegex = ($regexes | %{ '^' + $_ + '$' }) -join '|'
# match against that regex
$SpelledOutArray -notmatch $singleRegex
虽然我没有测试,但它有可能比检查循环中的所有内容更快。此外,非常长的正则表达式也可能会带来麻烦。
答案 1 :(得分:2)
将我的头撞在墙上好几个小时[...]似乎超级简单!
这可能暗示它并非超级简单。你试图交叉匹配两个列表:红色到红色,黄色,蓝色......然后蓝色到红色,黄色,蓝色......然后绿色到红色,黄色,蓝色...... 。 30次比较,但你只发生了5次循环。
你需要更多。
$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
# Loop once over the spelled out items
foreach($Item in $SpelledOutArray)
{
# for each one, loop over the entire WildCard array and check for matches
$WildCardMatches = foreach ($WildCard in $WildCardArray)
{
if ($item -like $WildCard) {
$Item
}
}
# Now see if there were any wildcard matches for this SpelledOut Item or not
if (-not $WildCardMatches)
{
$Item
}
}
并且WildCardArray上的内部循环可以成为过滤器,但您必须过滤数组,而不是像代码那样过滤单个项目。
$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
foreach($Item in $SpelledOutArray)
{
$WildCardMatches = $wildcardarray | Where { $item -like $_ }
if (-not $WildCardMatches)
{
$Item
}
}
我猜你可以把它混合成一个不清楚的双重过滤器,如果你不得不这样做。
$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
$SpelledOutArray |Where {$item=$_; -not ($WildCardArray |Where {$item -like $_}) }
答案 2 :(得分:1)
$WildCardArray = @("RED-*.htm", "*.yellow", "BLUE!.txt", "*.green", "*.purple")
$SpelledOutArray = @("RED-123.htm", "456.yellow", "BLUE!.txt", "789.green", "purple.102", "orange.abc")
$WildCardArray | %{$str=$_; $SpelledOutArray | ? {$_ -like $str} }
其他解决方案,而不是短暂的
$WildCardArray |
%{$current=$_; $SpelledOutArray | %{ [pscustomobject]@{wildcard=$current; value=$_ }}} |
where {$_.value -like $_.wildcard }