保持第一个正则表达式匹配并丢弃其他人

时间:2015-10-08 14:15:23

标签: regex powershell

是的另一个正则表达式问题...我在使用PowerShell从循环浏览文件夹时从文件名中提取一个简单的数字:

# sample string "ABCD - (123) Sample Text Here"

Get-ChildItem $processingFolder -filter *.xls | Where-Object {
    $name = $_.Name
    $pattern = '(\d{2,3})'
    $metric = ([regex]$pattern).Matches($name) | { $_.Groups[1].Value }
}

我要找的是括号括起来的数字。这是成功的,但它看起来是$ _。名称实际上抓取的不仅仅是文件的名称,正则表达式最终会拾取其他一些我不想要的位。

我理解为什么,因为它正在通过每个正则表达式匹配作为一个对象并从每个值中取出值并加入$ metric。我需要一些帮助来编辑代码,所以它只会困扰第一个对象。

如果我没有对比赛的实际内容感到困扰,我会使用-match等,但需要保留。

2 个答案:

答案 0 :(得分:1)

我没有看到$_.Groups[1].Value之前的cmdlet调用应该是ForEach-Object,但这是次要的。我们需要对您的正则表达式模式进行一些小改进,并考虑括号,但不要在回报中包含它们。

$processingFolder = "C:\temp"
$pattern = '\((\d+)\)'
Get-ChildItem $processingFolder -filter "*.xls" | ForEach-Object{
    $details = ""
    if($_.Name -match $pattern){$details = $matches[1]}
    $_ | Add-Member -MemberType NoteProperty -Name Details -Value $details -PassThru
} | select name, details

这将循环所有文件并尝试匹配括号中的数字。如果有多个匹配,则应该只接受第一个匹配。我们使用捕获组来忽略结果中的括号。接下来,我们使用Add-Member创建一个名为Details的新属性,该属性将包含匹配的值。

目前,这将返回$processingFolder中的所有文件,但简单的Where-Object{$_.Details}将仅返回已填充属性的文件。如果您需要制作其他属性,可以将Add-Member链接在一起。只是不要忘记-passthru

如果您需要使用多个自定义参数进行该路由,您也可以创建自己的新对象。它肯定会更简洁。 last question I answered就是一个例子。

答案 1 :(得分:0)

在对自己返回的数据(System.Text.RegularExpressions.MatchCollection)进行一些研究之后,我找到了Item方法,所以在$ metric上调用它就像这样:

$name = '(111) 123 456 789 Name of Report Here 123'
$pattern = '(\d{2,3})'
$metric = ([regex]$pattern).Matches($name)
Write-Host $metric.Item(1)

虽然可能不是最好的方法,但它会回归我现在所期待的。