日志文件上的PowerShell正则表达式捕获太多

时间:2015-11-10 19:45:33

标签: regex powershell

我试图从日志文件中提取一些文本,但我遇到了问题。 我正在处理的示例文本是:

ahksjhadjsadhsah
sakdsjakdjks
ksajdksaj
REF=35464
sadsad
213213
213
2
13

我需要提取价值" 35464" (REF编号)。我对正则表达式的了解有限,但想到了REF =([0-9] +)'会这样做。

现在我不确定读这个文件的效果如何,所以我尝试了几种方法:

select-string -path e:\powershell\log.txt -pattern 'REF=([0-9]+)' | % { $_.Matches } | % { $_.Value }

这给了我" REF = 35464" - 我不明白(为什么REF =包括在内),因为我认为'捕获'只是()'中的部分?

我也尝试过:

$data=Get-Content e:\powershell\log.txt
$data -match 'REF=([0-9]+)'
$Matches

但是$ Matches是空的。

我也尝试了类似于上面的方法,但是逐行,例如:

foreach ($line in $data)
{
    $line -match 'REF=([0-9]+)'
}

我要么没有匹配,要么完全匹配(包括REF =部分)。我也尝试过小组(即'(REF =)([0-9] +)'),我无法得到我需要的东西。

我该如何阅读文件?我的正则表达式出了什么问题?

我只需将此提取的值作为可用变量。

2 个答案:

答案 0 :(得分:1)

可能是您尝试访问捕获组的方式

我将这个快速静态类放在一起,以说明如何获得您正在寻找的匹配。

注意:我正在使用正则表达式上的@符号和输入字符串来使它们成为文字。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace SkunkWorks.RegexPractice
{
    public static class RegexPractice2
    {
        public static string input = @"ahksjhadjsadhsah
        sakdsjakdjks
        ksajdksaj
        REF=35464
        sadsad
        213213
        213
        2
        13";

        static string pat = @"REF=([0-9]+)";

        public static void Do()
        {
            Regex r = new Regex(pat, RegexOptions.IgnoreCase);

            Match m = r.Match(input);

            int matchCount = 0;

            while (m.Success)
            {
                Console.WriteLine("Match" + (++matchCount));
                for (int i = 1; i <= 2; i++)
                {
                    Group g = m.Groups[i];
                    Console.WriteLine("Group" + i + "='" + g + "'");
                    CaptureCollection cc = g.Captures;
                    for (int j = 0; j < cc.Count; j++)
                    {
                        Capture c = cc[j];
                        System.Console.WriteLine("Capture" + j + "='" + c + "', Position=" + c.Index);
                    }
                }
                m = m.NextMatch();
            }
        }
    }
}

答案 1 :(得分:0)

当我需要从字符串数组中提取子字符串时,我通常会使用在$Matches语句中使用-match运算符生成的自动变量Where 。像这样:

$Data | Where{$_ -match "REF=([0-9]+)"} | ForEach{$Matches[1]}

现在,$Matches变量将有一个数组。第一个条目将是它匹配的整行,第二个对象将只是捕获的文本,这就是我指定[1]的原因。现在,关于您正在匹配的RegEx ......技术上它是可以接受的,但它不是非常具体,所以它真的可以返回自[0-9]+以来的第一个数字属于[0-9]范围的1个或多个字符。如果您想确保获得所有数字,可以通过在匹配中使用行尾字符$来告诉它将所有内容放到行尾:REF=([0-9]+)$ 。我们无法确定数字后面是否有任何空格,因此您可能也希望使用\s符号来查找任何空白字符(空格,制表符,等等) ,并使用后面的星号,这意味着零或更多。然后它变成REF=([0-9]+)\s*$,它可以让你完全找到你想要的东西。最后,我会使用\d而不是[0-9],因为它做同样的事情,而且它更短更简单,专门为工作而做。所以,我们有:

$Data | Where{$_ -match "REF=(\d+)\s*$"} | ForEach{$Matches[1]}

这是逐步细分的,并在此解释:https://regex101.com/r/dG7jC7/1