如何比较if语句上的多个通配符模式?
if ($file.Name -like "*test*", "*.tmp")
{
# do something
}
不幸的是,无论是-like
(通配符匹配运算符)还是-match
(正则表达式匹配运算符)都不支持模式的数组从PowerShell 7.2.x开始:
-
拥有这种能力(使用任何一个模式匹配被认为是整体匹配)将是有用的;GitHub issue #2132要求在未来的PowerShell (Core)版本中实现它。
-
当你试图在RHS上使用数组时,PowerShell目前报告没有错误,它的当前行为实际上是无用的:数组是stringized形成一个单个字符串,这意味着它的元素与空格连接;即
$file.Name -like "*test*", "*.tmp"
与$file.Name -like "*test* *.tmp"
相同
然而,作为解决方案您可以使用-match
与单个regex模式,该模式使用替代(|
)匹配多个值之一:
if ($file.Name -match 'test|.tmp$') {
# do something
}
注意:
相反,如果您希望-match
默认匹配子字符串,因此不需要与*
通配符元字符等效的正则表达式。- 模式出现在某个位置,则需要锚定模式,例如使用上面的
$
来断言子表达式.tmp
匹配字符串的结尾。
- 模式出现在某个位置,则需要锚定模式,例如使用上面的
正则表达式比通配符强大得多,它有更多的元字符,可能需要用
转义;在这种情况下,匹配任何字符的元字符
.
必须转义为.
,以便匹配为文字.
- 对于(sub)字符串的程序化转义要在正则表达式中逐字解释,使用
[regex]::Escape()
,例如[regex]::Escape('.tmp')
,生成'.tmp'
。
- 对于(sub)字符串的程序化转义要在正则表达式中逐字解释,使用
如果您更喜欢使用-like
,则需要两个操作,您必须与-or
连接,如js2010在对问题的评论中所示:
if ($file.Name -like '*test*' -or $file.name -like '*.tmp') {
# do something
}
如果模式的数量很大或事先不知道,使用循环,例如通过[intrinsic.ForEach()
方法](intrinsic.Where()
方法):
$patterns = '*test*', '*.tmp' # Array of patterns
if ($patterns.Where({ $file.Name -like $_ }, 'First')) {
# do something
}
最后,值得注意的是Get-Item
andGet-ChildItem
支持-Include
(和-Exclude
)参数支持多个模式(不像-Filter
),所以你可以预过滤你的文件,而不需要检查他们的名字;例如:Get-Item .* -Include *test*, *.tmp
不幸的是,-Include
和-Exclude
是出了名的挑剔,除了(大多数情况下)也使用-Recurse
;例如,使用Get-ChildItem . -Include *test*, *.tmp
将不按预期工作-详细信息请参阅此回答。