我正在尝试运行使用字母日期命名的文件,并相应地设置文件日期时间。我的代码运行正常,当我注意到这个问题时,我已经准备好考虑它了。我的代码应检测两个日期并生成错误,但事实并非如此。我已经提取了相关代码,并重新创建了问题:
$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。我搜索了很多(我认为),并没有提出任何有用的信息。 有什么建议? 提前谢谢了, 戴夫
答案 0 :(得分:7)
PowerShell的-match
运算符只查找每个输入字符串的第一个匹配(如果有),因为它的目的是 test for a (any)匹配,无论是否有多个匹配。
请注意,如果LHS是数组,则单个-match
表达式可以包含多个输入字符串,在这种情况下,返回匹配的元素数组;例如:'foo', 'bar', 'baz' -match 'b'
产生数组'bar', 'baz'
。但是,对于每个数组元素,只会再次测试单个匹配,并且在这种情况下甚至不会填充自动$Matches
变量 - 请参阅bottom。 / SUP>
以下所有命令都假定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
运算符时,只能$Matches
既未填充也未重置。-match
返回$true
)
-match
返回$false
),则预先存在的$Matches
值(如果有)保持不变。 $Matches
是[hashtable]
个实例,其中包含以下条目:
0
的条目是整个匹配 - 根据定义,此密钥始终存在。<n>
的条目是 - 未命名 - 与索引<n>
匹配的捕获组。<name>
的条目是名称捕获组<name>
匹配的内容。 $Matches
(可能)还包含捕获组值的事实证明了其复数名称 - 尽管只匹配单个出现的正则表达式。< / p>
[1]要检查单个对象的类型或集合元素的类型,请管道Get-Member:([regex]::Matches('foo', 'o')) | Get-Member
要检查集合本身的类型,请将其传递给Get-Member -InputObject
:
Get-Member -InputObject ([regex]::Matches('foo', 'o'))