【问题标题】:Get path based on regex Powershell基于正则表达式 Powershell 获取路径
【发布时间】:2022-01-07 22:32:41
【问题描述】:

我查询了注册表以获取我正在寻找的文件路径。但是,我需要转到较低的一个目录来检索我需要的一些文件信息。我试图匹配的模式是OfficexxOFFICExx。我似乎无法找到我需要的路径。

从注册表中找到路径:C:\Program Files\Microsoft Office

我需要的是:C:\Program Files\Microsoft Office\Officexx

代码:

$base_install_path = "C:\Program Files\Microsoft Office";
$full_install_path = $base_install_path+'\Office[\d+.*]'
Write-Output $full_install_path;  

这会返回:

C:\Program Files\Microsoft Office\Office[\d+.*] 

期望的输出:

C:\Program Files\Microsoft Office\Office15

这不可能是任何两位数#^^

【问题讨论】:

  • $base_install_path+'\Office[\d+.*]' 是一个字符串连接,你试过用Get-ChildItem 搜索路径吗?这应该是您代码的一部分。

标签: regex windows powershell glob


【解决方案1】:

Santiago Squarzon's 有用的评论为基础:

# Find all child directories matching the given wildcard pattern, if any.
Get-ChildItem -Directory -Path "$base_install_path\Office[0-9][0-9]*"
  • bash 等 POSIX 兼容的 shell 不同,PowerShell 确实支持不带引号的字符串的自动通配(与文件名匹配的模式,称为 filename expansion),而是需要显式使用Get-ChildItemGet-Item cmdlet;例如,bash 命令 pattern='*.txt'; echo $pattern 在 PowerShell 中的等价物是 $pattern='*.txt'; Get-ChildItem -Path $pattern

    • 请注意,描述匹配文件或目录的 对象 由这些 cmdlet 输出;根据需要使用它们的 属性,例如(Get-ChildItem $pattern).Name(Get-ChildItem $pattern).FullName(完整路径)。使用 Get-ChildItem $pattern | Get-Member -Type Properties 查看所有可用属性。
  • 这些 cmdlet 的 -Path 参数需要 PowerShell wildcard expression 来执行所需的匹配,并且顶部命令中的表达式与 正好两个 位数字 ([0-9][0-9]) 匹配,然后是零个或多个个字符 (*),无论它们是什么(可能包括额外的数字)。

    • 注意:只有 PowerShell 的通配符语言 - 被 -Path-Include / -Exclude 参数(以及在许多其他情况下)接受 - 支持字符 范围(例如 [0-9] 匹配任何十进制数字)和 sets(例如 [._] 匹配 ._)。相比之下,Get-ChildItem-Filter 参数使用 文件系统 API 的通配符语言(正如 cmd.exe 所做的那样),支持它们,并且还展示了遗留的怪癖 - 请参阅 this answer 了解更多信息。

    • 虽然 PowerShell 的通配符范围和集合基本上与正则表达式(正则表达式,见下文)中的工作方式相同,但 支持特定于正则表达式的转义序列,例如 \d,而且您通常不能量化他们;也就是说,像 [0-9] 这样的东西只匹配一个位。


鉴于通配符模式仅支持一个,非特定重复构造,即上述*,匹配特定范围数字 - 例如 1 或 2 最多特定计数 - 例如 正好两个 - 需要基于 regex 进行后过滤(这是您尝试使用的):

# Find all child directories matching the given regex, if any.
# Matches 'Office' at the start of the name (^),
# followed by 1 or 2 ({1,2}) digits (\d), 
# followed by at least non-digit (\D), if any (?)
Get-ChildItem -Directory -LiteralPath $base_install_path |
  Where-Object Name -match '^Office\d{1,2}\D?'

至于你尝试了什么

  • [\d+.*] 是一个 regex,但您可能指的是 \d+.*,即一个或多个 (+) 数字 (\d) 后跟零个 (*) 字符,不管它们是什么 (.)

  • 在字符范围/集合表达式 ([...]) 内,+.* 使用逐字逐句,即它们不是元字符并匹配 literal .* 字符。

【讨论】:

  • 非常感谢您的解释。我认为只有两 (2) 种表达式类型:1) “通配符”(cmd '*'、'.' 和 '?')和 2)“正则表达式”。现在看来有三 (3) 种类型:1)“通配符”(cmd)、2)“PSWildcard”(添加显式字符范围)和 3)“正则表达式”。你说这是正确的观点吗?
  • @lit,是的-您可以将其视为两个通配符“方言”,其中 PowerShell 一个具有更多功能并且不受旧行为的影响。此外,PowerShell 方言在整个 PowerShell 中普遍使用,而不仅仅是在文件系统的上下文中。许多-Name 参数支持通配符;例如,Get-Process -Name ba* 查找名称以ba 开头的所有进程。文件系统使用的一个缺点是[] 是文件名中的合法字符,要求您明确使用-LiteralPath 参数以逐字匹配它们。
  • 基于此,我想知道是否应该对术语进行区分。 help Get-Process -Parameter Name 的输出提到了“通配符”。但是,尚不清楚这是传统的cmd 通配符还是PSWildcard。
  • @lit,文件系统通配符方言的唯一上下文是Get-ChildItem-Filter 参数。 docs 当前状态,“过滤器字符串被传递给 .NET API 以枚举文件。API 仅支持 *? 通配符。” (这缺乏细节,但传达了最重要的区别)。换句话说:任何其他上下文中的通配符都是指 PowerShell 方言。
  • @cynicalswan77,你的意思是你只想要完整的路径stringsGet-ChildItem -Directory -Path "$base_install_path\Office[0-9][0-9]*" | ForEach-Object FullName 或者,作为表达式:(Get-ChildItem -Directory -Path "$base_install_path\Office[0-9][0-9]*").FullName
【解决方案2】:
Get-ChildItem -Path 'C:\Program Files\Microsoft Office\' -Directory | 
    Where-Object { $_.Name -match 'Office\d+' }

在您的正则表达式中,[] 是一个字符类,这意味着 [\d+.*] 不是“一个或多个数字”而是“反斜杠 OR d OR plus OR dot OR asterisk”。

PS C:\> "d+\" -match "[\d+]"
True

不是你要找的。​​p>

【讨论】:

  • 好点重新字符类,但请注意转义序列\d 识别为这样 - 尝试'1' -match '[\d]'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多