简体   繁体   English

使用Match和Regex

[英]Working With Match and Regex

I am working on a project that parses an incoming text file. 我正在研究一个解析传入文本文件的项目。 I am learning C# as I go. 我正在学习C#。 My current method for picking out the information I need is something like: 我当前用于挑选所需信息的方法如下:

string MyMatchString = @"a pattern to match";
Match MyMatch = Regex.Match(somestringinput, MyMatchString);
if (MyMatch.Succes)
{
   DoSomething(MyMatch.Value);
}

I am doing a lot of that. 我正在做很多事情。 I'd like to be able to combine the match and the test for success in one step. 我希望能够将比赛和测试成功结合在一起。 Looking through the Class listings, Regex has an IsMatch() method, but it doesn't appear that I can access the matched value (assuming it is successful). 浏览类列表,Regex有一个IsMatch()方法,但是看来我不能访问匹配的值(假设它成功了)。 I think I need a Match instance for that. 我想我需要一个Match实例。 I tried 我试过了

if ((Match MyMatch = Regex.Match(somestringinput, MyMatchString).Success)

but of course got a compile error. 但是当然有一个编译错误。

I am thinking a static method that takes the match pattern and the input then returns a bool is the way to go. 我在考虑采用匹配模式然后输入然后返回布尔值的静态方法。 Then I can just test for success, and if so grab the matched value. 然后,我可以测试是否成功,如果可以,则获取匹配的值。

You can use foreach 您可以使用foreach

string MyMatchString = @"a pattern to match";
foreach (Match match in Regex.Matches(somestringinput, MyMatchString))
{
    DoSomething(match.Value);
}

Optionally add break if you want only one match (or use .Take(1) ) 如果您只想要一个匹配项,则可以选择添加break (或使用.Take(1)

Well you can write an extension method for Regex which would give you some power. 好吧,您可以为Regex编写扩展方法,这将为您提供一些功能。 The trick is doing it without running the regex match twice, which could be a problem for your performance (note: this hasn't been tested, and it differs from your idea in that it requires a ready-made Regex object to work). 诀窍在于无需两次运行正则表达式匹配就可以做到这一点,这可能会影响您的性能(请注意:这尚未经过测试,与您的想法不同,它需要一个现成的Regex对象才能工作)。

public static class RegexExtensions {
    public static bool GetMatch(this Regex regex, string input, out string matched) {
        Match match = regex.Match(input);
        if (match.Success) {
            matched = match.Value;
            return true;
        }
        matched = null;
        return false;
    }
}

So you'd do something like 所以你会做类似的事情

string matched;
Regex regex = new Regex(pattern);
if (regex.GetMatch(inputstring, matched))
{ /* do something with 'matched' */ }
else
{ /* no match, 'matched' is null */ }

You might prefer to just return null in the failure case and the string otherwise and dispense with the boolean and the output parameter. 您可能更愿意在失败的情况下只返回null,否则返回字符串,而不必使用boolean和output参数。

You could implement the "Try" convention used by TryParse and TryGetValue . 您可以实现TryParseTryGetValue使用的“ Try”约定。

public static bool TryMatch(string input, string pattern, out Match match)
{
    var m = Regex.Match(input, pattern);
    if(m.Success)
    {
        match = m;
    }
    return m.Success;
}

// usage
string myMatchString = @"a pattern to match"; 
Match result = null;
if(TryMatch(somestringinput, myMatchString, out result))
{
    DoSomething(result.Value);
}

Alternatively, you can create higher-order functions that accept Action and Func delegates. 或者,您可以创建接受ActionFunc委托的高阶函数。

public void ActionOnMatch(string input, string pattern, Action<string> action)
{
    var m = Regex.Match(input, pattern);
    if(m.Success)
    {
        action(m.Value);
    }
}

public TResult FuncOnMatch<TResult>(string input, string pattern, 
    Func<string, TResult> func)
{
    var m = Regex.Match(input, pattern);
    if(m.Success)
    {
        return func(m.Value);
    }
    else
    {
        return default(TResult);
    }
}

/// usage
string pattern = @"a pattern to match"; 
ActionOnMatch(input, pattern, DoSomething);
var result = FuncOnMatch<string>(input, pattern, (val) => val);

If you just want an answer as a boolean value and dont want to store it dont use a variable match to store it. 如果您只想将答案作为布尔值而不希望存储它,则不要使用变量匹配来存储它。 You can just use Regex.Match to get the boolean value you want like this: 您可以只使用Regex.Match来获取所需的布尔值,如下所示:

if (Regex.Match("a", MyMatchString).Success) { };

Creating the Match, testing for success and using the results are separate steps, by design. 根据设计,创建比赛,测试成功和使用结果是单独的步骤。 There might be ways around that, but you'd be fighting the framework, and possibly making your code a little less readable for other developers. 可能有一些解决方法,但是您可能会与框架发生冲突,并可能使代码对其他开发人员的可读性降低

If you're parsing a file, you might consider an alternate approach using Linq. 如果要解析文件,则可以考虑使用Linq的另一种方法。 Depending on exactly what you mean by DoSomething , this might at least make the code a little less tedious. 根据DoSomething确切含义,这至少可以使代码少一点乏味。

Regex re = new Regex(@"(?<prop1>pattern part 1)(?<prop2>pattern part 2)");

var goodLines = 
    from line in File.ReadAllLines(inputFile)
    let m = re.Match(line)
    where m.Success
    select new {
        Prop1 = m.Groups["prop1"].ToString(),
        Prop2 = m.Groups["prop2"].ToString()
    }

foreach (var goodLine in goodLines) {
    DoSomething(goodLine);
}

Here we're defining named capture groups within the regex, and using those named captures to populate an anonymous type. 在这里,我们在正则表达式中定义命名捕获组,并使用这些命名捕获来填充匿名类型。 Then we're looping over the collection of those anonymous objects returned by the Linq expression. 然后,我们遍历Linq表达式返回的那些匿名对象的集合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM