解析逻辑证明非常复杂

时间:2016-01-27 11:45:25

标签: c# regex

我有一个我必须解析的字符串,从中正确设置类变量。字符串结构很糟糕但我不能改变它。我试过解析它,但没有一个好方法没有问题。字符串本身是一组属性和参数,用于从cmd行触发exe。

我已经将它放在一个易于阅读的方式,但知道这是一个连续的字符串。

以下是有关如何阅读此行的规则。 对于每个'non-dll'命令,您可以期待单个键和值对。对于dll行,在初始dll =之后可以有一个或多个键值对,'即'dll'元素包含0或更多keyValue或由空格分割的独立值。例如 dll = oneMoreDll,andItsParam = value anotherParam = value lastParam = value value

输入字符串

  

time = value1 size = value2 dll = aDllName dll = anotherDllName,someParam = ParamValue dll = yetAnotherDll,someOhterParam = anotherParamValue aStandAloneValue dll = oneMoreDll,andItsParam = value anotherParam = value lastParam = value

我希望能够将此字符串解析为以下格式,我想的是字符串数组中的每一行。

我试过用空格分裂然后'dll'但是我的正则表达不是划伤或不可能(我确定不是)。救命啊!

所需的输出元素,存储在String数组中

time=value1 
size=value2 
dll=aDllName 
dll=anotherDllName, someParam=ParamValue  
dll=yetAnotherDll, someOhterParam=anotherParamValue aStandAloneValue
dll=oneMoreDll, andItsParam=value anotherParam=value lastParam=value

3 个答案:

答案 0 :(得分:2)

以下情况应该有效,至少对于样本案例。

  1. 按''
  2. 拆分字符串
  3. 将每个子字符串拆分为'='。如果没有'=',我们只需要左侧。
  4. 我们现在留下的结构看起来像这样:

    { left = attribute1, right = value1 }, { left = attribute2, right = value2 }, { left = aStandAloneValue }

    现在,我们需要按照之前的'dll'对每个项目进行分组。我正在使用this answer中的扩展方法来帮助解决这个问题。

    基本上,它将分组直到条件满足。在我们的例子中,当我们点击'dll'条目时,我们想要停止分组。或者,如果我们还没有点击'dll'条目,那么我们总是创建一个新组。

    其余的只是格式化输出(在您的情况下可能不需要)。

    var inStr = "time=value1 size=value2 dll=aDllName dll=anotherDllName, someParam=ParamValue dll=yetAnotherDll, someOhterParam=anotherParamValue aStandAloneValue dll=oneMoreDll, andItsParam=value anotherParam=value lastParam=value";
    
    bool isBeforeAnyDll = true;
    
    var result = inStr.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
        .Select(r => {
            var split = r.Split('=');
            if (split.Length == 1)
                return new { left = split[0], right = (string)null };
    
            var left = split[0];
            var right = split[1];
            return new { left, right };
        })
        .GroupAdjacentBy((l, r) =>  {
            return r.left == "dll" 
                 ? isBeforeAnyDll = false
                 : !isBeforeAnyDll;
        })
        .Select(g => string.Join(" ", 
            g.Select(gg => { 
                if (gg.right == null)
                    return gg.left;
                return string.Format("{0}={1}", gg.left, gg.right);
            })));
    
    
    //https://stackoverflow.com/a/4682163/563532
    public static class LinqExtensions
    {
        public static IEnumerable<IEnumerable<T>> GroupAdjacentBy<T>(
            this IEnumerable<T> source, Func<T, T, bool> predicate)
        {
            using (var e = source.GetEnumerator())
            {
                if (e.MoveNext())
                {
                    var list = new List<T> { e.Current };
                    var pred = e.Current;
                    while (e.MoveNext())
                    {
                        if (predicate(pred, e.Current))
                        {
                            list.Add(e.Current);
                        }
                        else
                        {
                            yield return list;
                            list = new List<T> { e.Current };
                        }
                        pred = e.Current;
                    }
                    yield return list;
                }
            }
        }
    }
    

    输出:

    time=value1 
    size=value2 
    dll=aDllName 
    dll=anotherDllName, someParam=ParamValue 
    dll=yetAnotherDll, someOhterParam=anotherParamValue aStandAloneValue 
    dll=oneMoreDll, andItsParam=value anotherParam=value lastParam=value 
    

    数据在.GroupAdjacentBy()后正确分组在一起,以下代码只是格式化输出。

答案 1 :(得分:0)

为什么不按Enviroment.NewLine然后按,拆分然后按第一个=符号拆分,将左边的部分作为变量名称,然后将右边的部分作为变量值?< / p>

答案 2 :(得分:0)

您可以使用Regex.Matches

使用以下正则表达式方法
using System;
using System.Linq;
using System.Text.RegularExpressions;
public class Test
{
    public static void Main()
    {
        var log = "time=value1 size=value2 dll=aDllName dll=anotherDllName, someParam=ParamValue dll=yetAnotherDll, someOhterParam=anotherParamValue aStandAloneValue dll=oneMoreDll, andItsParam=value anotherParam=value lastParam=value";
        var res = Regex.Matches(log, @"\bdll=(?:(?!\bdll=).)*|\w+=\w+")
                 .Cast<Match>()
                 .Select(p => p.Value)
                 .ToList();
        Console.WriteLine(string.Join("\n",res));
    }
}

请参阅IDEONE demoregex demo

正则表达式匹配2个替代方案:

  • \bdll= - 完整的单词dll=后跟......
  • (?:(?!\bdll=).)* - 零个或多个不是dll
  • 的字符
  • | - 或....
  • \w+=\w+ - 后跟=的一个或多个单词字符,后跟一个或多个单词字符。