解析逻辑证明非常复杂
本文关键字:非常 复杂 证明 | 更新日期: 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
至少对于示例案例,以下内容应该有效。
- 将字符串拆分为 ' '
- 按"="拆分每个子字符串。如果没有"=",我们只需选择左侧。
我们现在留下了一个看起来像这样的结构:
{ 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+
- 一个或多个单词字符