解析逻辑证明非常复杂

本文关键字:非常 复杂 证明 | 更新日期: 2023-09-27 18:32:02

我有一个必须解析的字符串,从中正确设置类变量。字符串结构不正确,但我无法更改它。我尝试过解析它,但没有一个好的方法可以毫无问题地做到这一点。字符串本身是一组属性和参数,用于从 cmd 行触发 exe。

我以一种更易于阅读的方式布置了它,但知道它是 1 个连续字符串。

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

value value

输入字符串

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

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

尝试过按空格拆分,然后按"dll"拆分,但我的正则表达式已经从头开始或不可能(我确定它不是)。帮助!

所需的输出元素,要存储在字符串数组中

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

解析逻辑证明非常复杂

至少对于示例案例,以下内容应该有效。

  1. 将字符串拆分为 ' '
  2. 按"="拆分每个子字符串。如果没有"=",我们只需选择左侧。

我们现在留下了一个看起来像这样的结构:

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

现在,我们需要按前一个"dll"对每个项目进行分组。我正在使用从此答案中提取的扩展方法来帮助您解决这个问题。

本质上,它将分组,直到满足条件。在我们的例子中,我们希望在点击"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()后全部正确分组在一起,以下代码只是格式化输出。

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

您可以使用以下正则表达式方法使用 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 演示和正则表达式演示

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

  • 'bdll= - 一个完整的词dll=后面...
  • (?:(?!'bdll=).)* - 零个或多个未dll字符
  • | - 或者....
  • 'w+='w+ - 一个或多个单词字符
  • 后跟=后跟一个或多个单词字符。