regex - PowerShell regex -match 只匹配一次

标签 regex powershell

我正在尝试遍历使用字母日期命名的文件,并相应地设置文件日期时间。我的代码工作正常,当我注意到这个问题时,我已经准备好认为它是完整的。我的代码应该检测两个日期并生成错误,但它没有。我已经提取了相关代码,并重新创建了问题:

$str = "test20001231 20170415.txt"
$match = ($str -match "(?<=\b|\D)20\d{6,6}(?=\b|\D)")
"$match"
"$($Matches.length)"
"$($Matches[0].ToString())"

给出这个输出:
True
1
20001231

我对正则表达式代码的理解是,它应该匹配所有以 20 开头的 8 位数字,无论它在字符串中的任何位置,除非它在另一个数字之后或之前。所以我期望 $Matches.length 为 2。

我已经在网上的许多地方测试了正则表达式代码,它与我期望的两个日期相匹配:
http://regexstorm.net/tester?p=%28%3f%3c%3d%5cb%7c%5cD%2920%5cd%7b6%2c6%7d%28%3f%3d%5cb%7c%5cD%29&i=test20001231+20170415.txt
http://www.phpliveregex.com/p/jLA

该问题适用于 PS 和 PS ISE。我搜索了很多(我认为),但没有发现任何有用的东西。
有什么建议?
提前谢谢了,
戴夫

最佳答案

PowerShell 的 -match运算符只查找每个输入字符串的第一个匹配项(如果有) ,因为它的目的是测试(任何)匹配项,而不管是否有多个匹配项。
注意单-match表达式可以有多个输入字符串,如果 LHS 是一个数组,则返回匹配元素的数组;例如:'foo', 'bar', 'baz' -match 'b'产生数组 'bar', 'baz' .但是,对于每个数组元素,仅再次测试单个匹配项,并且自动 $Matches在这种情况下不填充变量 - 见底部。
下面的所有命令都假定 PSv3+,但也可以在 v2 中运行。
您需要使用 .NET 框架的 [regex] 获取多个匹配项的类 :

PS> ([regex]::Matches('test20001231 20170415.txt', '(?<=\b|\D)20\d{6,6}(?=\b|\D)')).Value
20001231
20170415
[regex]::Matches()输出 [System.Text.RegularExpressions.Match] 的集合实例[1] 其.Value属性包含匹配项。
注意如何.Value应用于整个合集,在 PSv3+ 中
自动将集合成员的属性值作为数组返回。
要获得匹配的数量:
PS> ([regex]::Matches('test20001231 20170415.txt', '(?<=\b|\D)20\d{6,6}(?=\b|\D)')).Count
2

另一种选择是使用 Select-String -AllMatches ,输出 [Microsoft.PowerShell.Commands.MatchInfo]实例
谁的.Matches属性包含每行的集合 [System.Text.RegularExpressions.Match]实例:
PS> ('test20001231 20170415.txt' |
    Select-String -AllMatches '(?<=\b|\D)20\d{6,6}(?=\b|\D)').Matches.Value
20001231
20170415
如上,代入.Count.Value输出匹配的数量。
注意使用 Select-String使用单个输入字符串 有点笨拙,但它是 用于大型输入集合的正确工具 ,例如文件的行。

选读:自动$Matches变量:
自动$Matches变量已填充(从 PSv5.1 开始):
  • 仅当您使用 -match 时运算符(operator)
  • LHS 是一个标量
  • 相比之下,在 LHS 上有一个阵列,$Matches既不填充也不重置。

  • 并找到匹配项( -match 返回 $true )
  • 如果没有找到匹配项( -match 返回 $false ),一个预先存在的 $Matches值(如果有)保持不变。

  • $Matches[hashtable]具有以下条目的实例:
  • key 0的条目是整个匹配项 - 根据定义,此键始终存在。
  • key <n>的条目是 - 未命名 - 带有索引的捕获组 <n>匹配。
  • key <name>的条目是命名捕获组 <name>匹配。

  • 事实$Matches (可能)还包含捕获组值证明其复数名称合理 - 尽管仅与给定正则表达式的单个匹配有关。

    [1] 要检查单个对象的类型或集合元素的类型,请通过管道发送至 Get-Member :([regex]::Matches('foo', 'o')) | Get-Member要检查集合本身的类型,请将其传递给 Get-Member -InputObject :Get-Member -InputObject ([regex]::Matches('foo', 'o'))

    关于regex - PowerShell regex -match 只匹配一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43421755/

    相关文章:

    javascript - 如何在正则表达式中使用变量?

    jquery - 使用 jQuery 从字符串中获取完整 URL

    java - 匹配 C 风格多行注释的正则表达式

    java - 正则表达式字符串验证

    regex - vi vim 删除一个特殊 block 中的单词

    powershell - 如何支持多个互斥的参数?

    internet-explorer - 对Windows Powershell中弹出窗口的引用

    powershell - 如何在同一个输入框中有多个输入字段

    Powershell(cmd too) 无法识别特殊字符 "ą, ę"等

    string - 如何在 Powershell 中运行 ffmpeg 命令并将变量传递给它?