提问人:JohnLBevan 提问时间:7/21/2023 更新时间:7/21/2023 访问量:44
基于正则表达式创建简单的通配符/过滤器模式
Create simple wildcard / filter pattern based on regex
问:
上下文
在执行过滤器操作时,通常最好将过滤器推到尽可能远的上游,以获得良好的性能;例如,如果我使用 PowerShell 从目录中获取所有文件,则更可取。Get-ChildItem 'c:\temp\' -Filter '*.txt'
Get-ChildItem 'c:\temp\' | Where-Object {$_.Name -like '*.txt'}
但是,在某些情况下,上游组件不会给我们提供将内容推送到上游的选项;例如,如果我们想查找任何图像文件,我们要么必须多次调用以将每种类型的不同值传递给,但会导致多次遍历目录并可能返回相同的文件(如果它们与多个过滤器匹配);或者我们必须在下游执行过滤。Get-ChildItem
Filter
如果我正在搜索图像文件(对于这个特定的示例,假设是:),一种方法可能是作为过滤器发送到提供程序,因此我们在早期就排除了很多候选者,然后过滤我们感兴趣的特定扩展名下游。'*.png', '*.gif', '*.jpg', '*.jpeg'
'*.*g*'
问题
有没有一种已知的方法来提取表示正则表达式部分实现的“类似模式/掩码”?
例如,所以我可以实现这样的东西:
Function Get-ImageFiles {
Param(
[Parameter(Mandatory)]
[string]$LiteralPath
,
[Parameter()]
[string]$Pattern = '\.(?:png|gif|jpg|jpeg)$'
)
$simpleMask = ConvertTo-SimpleMask -RegexPattern $Pattern
[System.IO.Directory]::EnumerateFiles($LiteralPath, $simpleMask) |
Select-String -Pattern $Pattern -Raw
}
# for '\.(?:png|gif|jpg|jpeg)$' simpleMask would be '*.*g*'
# for '\.(?:jpg|jpeg)$' simpleMask would be '*.jp*g'
# for '\.(?:png|gif|jpg|jpeg|webp)$' simpleMask would be '*.*'
注意:在这个问题中,我使用了PowerShell作为我的示例代码;但我对这个“正则表达式到简单过滤器”问题的任何解决方案感兴趣。这更像是一个好奇心问题,而不是特定于上述示例用例。
答:
不可以,您不能将任意正则表达式模式转换为通配符模式,因为通配符模式本质上是正则表达式的子集。
如果性能是你最关心的问题,请枚举所有文件并根据属性进行筛选 - 这样你就根本不需要任何可变长度的匹配功能,并且比较将比任何正则表达式或通配符比较快得多:Extension
Get-ChildItem -File |Where-Object Extension -in '.png','.gif','.jpg','.jpeg'
如果我们想找到任何图像文件,我们要么必须多次调用,将每种类型的不同值传递给 Filter
Get-ChildItem
该参数允许传递多个模式,因此只需要一个 Get-ChildItem
调用。-Include
然而:
与 不同,它不会在源进行筛选,并且要求 cmdlet 枚举所有项,并自行将它们与指定的模式进行匹配。
-Filter
-Include
除非您使用 ,否则您必须结束输入路径才能按预期工作 - 有关详细信息,请参阅此答案。
-Recurse
*
-Include
注意:vs支持的通配符“方言”。 (和 ) 不同:使用基础文件系统 API 的通配符模式,这些 API 的功能不如 PowerShell 的通配符,并且有许多遗留的怪癖 - 有关详细信息,请参阅此答案。
-Filter
-Include
-Exclude
-Path
-Filter
因此,例如:
# Note the trailing * in the (positionally implied) -Path argument,
# to make -Include work as intended.
# This isn't necessary if -Recurse is also used.
Get-ChildItem c:\temp\* -Include *.png, *.gif, *.jpg, *.jpeg
为了提高性能,您实际上可以将参数与 结合使用,这意味着您将使用 -Filter
获得快速的初步过滤,但使用误报,然后模式会消除这些误报:-Filter
-Include
-Include
# Note the use of *both* -Filter and -Include
Get-ChildItem c:\temp\* -Filter *.*g* -Include *.png, *.gif, *.jpg, *.jpeg
请注意,诸如 之类的模式不会限制部件与扩展名的匹配,并且还会匹配文件名,例如 或*.*g*
*g*
f.g.txt
f._g.txt
下一个:在 C 中处理转义序列#
评论