从C#中的格式化字符串解析值

时间:2020-12-25 02:06:46

How can I parse multiple values from a formatted string in C#?

如何从C#中的格式化字符串解析多个值?

The string is in this format: "blah blah blah (foo:this, bar:that)"

字符串采用以下格式:“blah blah blah(foo:this,bar:that)”

I need to parse out the foo and the bar value. The parentheses are always at the end of the line.

我需要解析foo和bar值。括号总是在行的末尾。

Edit: Sorry... that wasn't very clear. What I meant was I need to know the "foo" value and the "bar" value, so that I can say, somewhere else, "foo is this" and "bar is that".

编辑:对不起......那不是很清楚。我的意思是我需要知道“foo”值和“bar”值,以便我可以说,在其他地方,“foo就是这个”,“bar就是那个”。

Thanks

4 个解决方案

#1


1  

EDIT: updated after OP clarification.

编辑:OP澄清后更新。

This should do:

这应该做:

string input = "blah blah blah (foo:this, bar:that,1:one,2:two)";
string pattern = @"\((?:(?<Values>.*?:[^,\s]+)[,\s]*)+\)";
foreach (Match m in Regex.Matches(input, pattern))
{
    foreach (Capture c in m.Groups["Values"].Captures)
    {
        string[] values = c.Value.Split(':');
        Console.WriteLine("{0} : {1}", values[0], values[1]);
    }
}

This outputs:

  • foo : this
  • foo:这个

  • bar : that
  • 吧:那个

  • 1 : one
  • 1:一

  • 2 : two
  • 2:两个

If you need to ensure the match only occurs at the end of the string, rather than match similar formatted values elsewhere in the string, add $ to the end of the pattern:

如果您需要确保匹配仅发生在字符串的末尾,而不是匹配字符串中其他位置的类似格式化值,请将$添加到模式的末尾:

string pattern = @"\((?:(?<Values>.*?:[^,\s]+)[,\s]*)+\)$";

#2


0  

Regular expressions should not be used for parsing if possible, only lexing. Pass the lexed tokens into a finite state machine for the actual parsing.

正则表达式不应该用于解析,如果可能的话,只有lexing。将lexed标记传递到有限状态机以进行实际解析。

#3


0  

I'm making quite a few assumptions here based on your question, but this should get you headed in the right direction.

我根据你的问题在这里做了很多假设,但这应该让你朝着正确的方向前进。

#!/usr/bin/perl

my $input = "blah blah blah (foo:this, bar:that, foo2:150)";

my @ray = ($input =~ /.*?:(\w*)/g);
foreach $x (@ray)
{
    print "Value: '$x'\n";
}

Output:

Value: 'this'
Value: 'that'
Value: '150'

#4


0  

As for .NET you can use captures like this:

至于.NET,你可以使用这样的捕获:

> $s = "blah blah blah (foo:this, bar:that)"
> $result = [regex]::Match($s, '[^(]*\((?:\w+:(?<t>\w+),\s*)*\w+:(?<t>\w+)\)$')
> $result.Groups

Groups   : {blah blah blah (foo:this, bar:that), that}
Success  : True
Captures : {blah blah blah (foo:this, bar:that)}
Index    : 0
Length   : 35
Value    : blah blah blah (foo:this, bar:that)

Success  : True
Captures : {this, that}
Index    : 30
Length   : 4
Value    : that

> $result.Groups[1].captures
Index                                          Length Value
-----                                          ------ -----
20                                               4 this
30                                               4 that

it is code in PowerShell. However, PowreShell is based on .NET, so this should work in .NET.

它是PowerShell中的代码。但是,PowreShell基于.NET,所以这应该适用于.NET。

The parsing expression is based on the example you posted, so it skips everything up to ( and then begins parsing the values. Note that (?:..) is noncapturing group so it doesn't appear in results.

解析表达式基于您发布的示例,因此它会跳过所有内容(然后开始解析值。请注意(?:..)是非捕获组,因此它不会出现在结果中。

#1


1  

EDIT: updated after OP clarification.

编辑:OP澄清后更新。

This should do:

这应该做:

string input = "blah blah blah (foo:this, bar:that,1:one,2:two)";
string pattern = @"\((?:(?<Values>.*?:[^,\s]+)[,\s]*)+\)";
foreach (Match m in Regex.Matches(input, pattern))
{
    foreach (Capture c in m.Groups["Values"].Captures)
    {
        string[] values = c.Value.Split(':');
        Console.WriteLine("{0} : {1}", values[0], values[1]);
    }
}

This outputs:

  • foo : this
  • foo:这个

  • bar : that
  • 吧:那个

  • 1 : one
  • 1:一

  • 2 : two
  • 2:两个

If you need to ensure the match only occurs at the end of the string, rather than match similar formatted values elsewhere in the string, add $ to the end of the pattern:

如果您需要确保匹配仅发生在字符串的末尾,而不是匹配字符串中其他位置的类似格式化值,请将$添加到模式的末尾:

string pattern = @"\((?:(?<Values>.*?:[^,\s]+)[,\s]*)+\)$";

#2


0  

Regular expressions should not be used for parsing if possible, only lexing. Pass the lexed tokens into a finite state machine for the actual parsing.

正则表达式不应该用于解析,如果可能的话,只有lexing。将lexed标记传递到有限状态机以进行实际解析。

#3


0  

I'm making quite a few assumptions here based on your question, but this should get you headed in the right direction.

我根据你的问题在这里做了很多假设,但这应该让你朝着正确的方向前进。

#!/usr/bin/perl

my $input = "blah blah blah (foo:this, bar:that, foo2:150)";

my @ray = ($input =~ /.*?:(\w*)/g);
foreach $x (@ray)
{
    print "Value: '$x'\n";
}

Output:

Value: 'this'
Value: 'that'
Value: '150'

#4


0  

As for .NET you can use captures like this:

至于.NET,你可以使用这样的捕获:

> $s = "blah blah blah (foo:this, bar:that)"
> $result = [regex]::Match($s, '[^(]*\((?:\w+:(?<t>\w+),\s*)*\w+:(?<t>\w+)\)$')
> $result.Groups

Groups   : {blah blah blah (foo:this, bar:that), that}
Success  : True
Captures : {blah blah blah (foo:this, bar:that)}
Index    : 0
Length   : 35
Value    : blah blah blah (foo:this, bar:that)

Success  : True
Captures : {this, that}
Index    : 30
Length   : 4
Value    : that

> $result.Groups[1].captures
Index                                          Length Value
-----                                          ------ -----
20                                               4 this
30                                               4 that

it is code in PowerShell. However, PowreShell is based on .NET, so this should work in .NET.

它是PowerShell中的代码。但是,PowreShell基于.NET,所以这应该适用于.NET。

The parsing expression is based on the example you posted, so it skips everything up to ( and then begins parsing the values. Note that (?:..) is noncapturing group so it doesn't appear in results.

解析表达式基于您发布的示例,因此它会跳过所有内容(然后开始解析值。请注意(?:..)是非捕获组,因此它不会出现在结果中。