正则表达式奇怪的行为,将不符合我的需要

时间:2016-05-10 23:37:28

标签: c# regex

我有三种不同的输入。

<inverse content="HelloWorlD"/>
<reverse content="helloworld"/>
<repeat value="2" content="helloworld"/>

在第一个输入中,我需要反转内容中字符串中的字符。

在第二个问题上,我需要做同样的事情,但要反过来。

在第三个我需要重复字符串,当X是值编号时,该字符串在内容X中。

我正在使用Regex来匹配输入。

它完美匹配所有内容。

enter image description here

它适用于反向和反向命令,但是当我尝试匹配重复行时,它将它们放在两个不同的匹配中,这对我来说不起作用。

enter image description here

string line = Console.ReadLine();
Regex pattern = new Regex("(\\w+) \\w+=\"(\\w+)\"| \\w+=\"(\\w+)\"");

List<string> list = new List<string>();

while (line != "stop")
{
    MatchCollection matcher = pattern.Matches(line);

    foreach (Match match in matcher)
    {
        string command = match.Groups[1].ToString();
        string content;
        int value;

        switch (command)
        {
            case "inverse":
                content = match.Groups[2].ToString();
                list.Add(InverseContent(content));
                break;
            case "reverse":
                content = match.Groups[2].ToString();
                list.Add(ReverseContent(content));
                break;
            case "repeat":
                value = int.Parse(match.Groups[2].ToString());
                content = match.Groups[3].Value;
                for (int i = 0; i < value; i++)
                {
                    list.Add(content);
                }
                break;
        }
    }
    line = Console.ReadLine();
}

3 个答案:

答案 0 :(得分:1)

使用?使第二个值可选:

"(\\w+) \\w+=\"(\\w+)\"(\\s+\\w+=\"(\\w+)\")?"

对于&#34;重复&#34;如果它将产生组#2和#4中的值。

enter image description here

答案 1 :(得分:0)

试试这个正则表达式:

(\ w +)\ w + =“(\ d +){0,1}”\ w + =“(\ w +)”

答案 2 :(得分:0)

这可能有点矫枉过正,但无论如何我都会发布它。

由于您的数据似乎是格式良好的XML - 我们可以使用XML解析器来获取结构化的命令列表。这将使您的解决方案更容易测试并能够处理更复杂的情况。它将处理输入形成的情况,如<inverse content="HelloWorld"></inverse>,以及重新排序属性<repeat content="x" value="3" />而不是<repeat value="3" content="x" />。它还可以支持值内的任何随机输入(不仅仅是单词字符)。

如果你的输入被一个根元素包围(你可以自己插入,如果你不这样做) - 输入是格式良好的xml。例如:

//file: input.xml
<input>
  <inverse content="HelloWorld" />
  <reverse content="helloworld" />
  <repeat value="2" content="helloworld" />
</input>

然后我们可以构造一个类来表示输入命令列表,如下所示:

[XmlRoot("input")] //indicate that this class represents the xml file
public class CommandList
{   
    // tell the XmlSerializer which <element> belongs to which class.
    [XmlElement("repeat", typeof(Repeat))]
    [XmlElement("reverse", typeof(Reverse))]
    [XmlElement("inverse", typeof(Inverse))]
    public List<Command> Commands { get; } = new List<Command>();
}

Command类是abstract,有三种不同的实现,具体取决于元素:

public abstract class Command
{
    [XmlAttribute("content")]
    public string Content { get; set; }
    public abstract void Process(List<string> output);
}

在定义抽象类之后,我们可以将不同的命令创建为单独的类:

public class Inverse : Command
{
    public override void Process(List<string> output)
    {
        var inverseContent = this.Content; //todo: process
        output.Add(inverseContent);
    }
}
public class Reverse : Command
{
    public override void Process(List<string> output)
    {
        var reverseContent = this.Content; //todo: process
        output.Add(reverseContent);
    }
}

对于Repeat类,有一个额外属性value

public class Repeat : Command
{
    [XmlAttribute("value")]
    public int Value { get; set; }
    public override void Process(List<string> output)
    {
        for (int i = 0; i < this.Value; i++)
        {
            output.Add(this.Content);
        }
    }
}

然后,运行您的解决方案:

using System.IO;
using System.Xml.Serialization;

var serializer = new XmlSerializer(typeof(CommandList));
var result = (CommandList)serializer.Deserialize(File.OpenRead("input.xml"));
var output = new List<string>();
foreach (var command in result.Commands)
{
    command.Process(output);
}