我有一个我必须解析的字符串,从中正确设置类变量。字符串结构很糟糕但我不能改变它。我试过解析它,但没有一个好方法没有问题。字符串本身是一组属性和参数,用于从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
答案 0 :(得分:2)
以下情况应该有效,至少对于样本案例。
我们现在留下的结构看起来像这样:
{ 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));
}
}
正则表达式匹配2个替代方案:
\bdll=
- 完整的单词dll=
后跟...... (?:(?!\bdll=).)*
- 零个或多个不是dll
|
- 或.... \w+=\w+
- 后跟=
的一个或多个单词字符,后跟一个或多个单词字符。