C# 需要有关正则表达式匹配/替换模式的帮助吗

C# 需要有关正则表达式匹配/替换模式的帮助吗,c#,regex,C#,Regex,我在这里的最终目标是将以下字符串转换为JSON,但我会满足于通过将字段名与每个值相结合来更进一步的要求 样本数据: Field1:abc;def;Field2:asd;fgh; 使用Regex.Replace(),我需要它至少如下所示: Field1:abc,Field1:def,Field2:asd,Field2:fgh 最终,如果可以通过Regex在一次调用中完成,那么这个结果将非常棒 {"Field1":"abc","Field2":"asd"},{"Field1":"def","Fi

我在这里的最终目标是将以下字符串转换为JSON,但我会满足于通过将字段名与每个值相结合来更进一步的要求

样本数据:

Field1:abc;def;Field2:asd;fgh;
使用Regex.Replace(),我需要它至少如下所示:

Field1:abc,Field1:def,Field2:asd,Field2:fgh
最终,如果可以通过Regex在一次调用中完成,那么这个结果将非常棒

{"Field1":"abc","Field2":"asd"},{"Field1":"def","Field2":"fgh"}
我尝试过这种模式的许多不同变体,但似乎都不正确:

(?:(\w+):)*?(?:([^:;]+);)
我能找到的另一个例子是做了一些类似的事情,但只是有足够的差异,我不能完全指出

这是我的解决办法。我不打算把它作为一个“解决方案”发布,因为我想把别人发布的解决方案归功于我。最后,我从每个贴出的解决方案中拿出一块,并提出了这个解决方案。感谢所有发帖的人。我认为这个解决方案编译、执行速度最快,结果最准确

    string hbi = "Field1:aaa;bbb;ccc;ddd;Field2:111;222;333;444;";

    Regex re = new Regex(@"(\w+):(?:([^:;]+);)+");
    MatchCollection matches = re.Matches(hbi);

    SortedDictionary<string, string> dict = new SortedDictionary<string, string>();

    for (int x = 0; x < matches.Count; x++)
    {
        Match match = matches[x];
        string property = match.Groups[1].Value;

        for (int i = 0; i < match.Groups[2].Captures.Count; i++)
        {
            string key = i.ToString() + x.ToString();
            dict.Add(key, string.Format("\"{0}\":\"{1}\"", property, match.Groups[2].Captures[i].Value));
        }
    }
    Console.WriteLine(string.Join(",", dict.Values));
string hbi=“Field1:aaa;bbb;ccc;ddd;Field2:111;222;333;444;”;
正则表达式re=新正则表达式(@“(\w+):(?:([^:;]+);)+”;
MatchCollection匹配=重新匹配(hbi);
SortedDictionary dict=新SortedDictionary();
for(int x=0;x

我认为正则表达式不是处理这个问题的最佳方法。您可能应该首先以分号分隔,然后在结果中循环查找以“Field1:”或“Field2:”开头的值,并将结果收集到字典中

将其视为伪代码,因为我没有编译或测试它:

string[] data = input.Split(';');
dictionary<string, string> map = new dictionary<string, string>();

string currentKey = null;
foreach (string value in data)
{
    // This part should change depending on how the fields are defined.
    // If it's a fixed set you could have an array of fields to search,
    // or you might need to use a regular expression.
    if (value.IndexOf("Field1:") == 0 || value.IndexOf("Field2:"))
    {
        string currentKey = value.Substring(0, value.IndexOf(":"));
        value = value.Substring(currentKey.Length+1);
    }
    map[currentKey] = value;
}
// convert map to json
string[]data=input.Split(“;”);
字典映射=新字典();
字符串currentKey=null;
foreach(数据中的字符串值)
{
//此部分应根据字段的定义方式进行更改。
//如果它是一个固定的集合,您可以搜索一组字段,
//或者您可能需要使用正则表达式。
if(value.IndexOf(“Field1:”)==0 | | value.IndexOf(“Field2:”)
{
字符串currentKey=value.Substring(0,value.IndexOf(“:”);
value=value.Substring(currentKey.Length+1);
}
map[currentKey]=值;
}
//将映射转换为json

我会选择正则表达式作为解析字符串的最简单、最直接的方法,但很抱歉,伙计,我不能想出一个足够聪明的替换字符串来一次性完成这项工作

我把它砍掉是为了好玩,下面的怪物完成了你需要的东西,尽管很可怕-/

Regex r=newregex(@“(?\w+:)*(?:(?(?:[^:;]+);)+))”;
var matches=r.matches(“字段1:abc;def;字段2:asd;fgh;moo;”;//修改以测试“不均匀”数据。
var tuples=new[]{new{FieldName=“”,Value=“”,Index=0}}}.ToList();tuples.Clear();
foreach(匹配中的匹配)
{
var matchGroups=match.Groups;
var fieldName=matchGroups[1]。捕获[0]。值;
int指数=0;
foreach(匹配组[2]中的捕获上限。捕获)
{
var tuple=new{FieldName=FieldName,Value=cap.Value,Index=Index};
tuples.Add(tuple);
索引++;
}
}
var maxIndex=tuples.Max(tup=>tup.Index);
var jsonitmlist=新列表();
对于(int a=0;atup.Index==a))
{
追加(string.Format(“\”{0}\”:\“{1}\”,”,tuple.FieldName,tuple.Value));
}
jsonBuilder.Remove(jsonBuilder.Length-1,1);//修剪最后一个逗号。
jsonBuilder.Append(“}”);
添加(jsonBuilder.ToString());
}
foreach(jsonItemList中的变量项)
{
//将项目写入文档流。
}

我有一个想法,应该可以用一种更简短、更清晰的方式来完成。最后它没有那么短,你可以质疑它是否更清晰。至少这是另一种解决问题的方法

var str = "Field1:abc;def;Field2:asd;fgh";
var rows = new List<Dictionary<string, string>>();
int index = 0;
string value;
string fieldname = "";

foreach (var s in str.Split(';'))
{
    if (s.Contains(":"))
    {
        index = 0;
        var tmp = s.Split(':');
        fieldname = tmp[0];
        value = tmp[1];
    }
    else
    {
        value = s;
        index++;
    }

    if (rows.Count < (index + 1))
        rows.Insert(index, new Dictionary<string, string>());

    rows[index][fieldname] = value;
}

var arr = rows.Select(dict => 
                   String.Join("," , dict.Select(kv => 
                       String.Format("\"{0}\":\"{1}\"", kv.Key, kv.Value))))
                   .Select(r => "{" + r + "}");
var json = String.Join(",", arr );
Debug.WriteLine(json);

如果LINQ的性能接近Regex,我很高兴。在大输入字符串上进行比较会很有趣,我同意。与我试图转换的数据相比,这里显示的相同数据非常小。真正的对象包含31个字段,可能包含100-200个对象。@Chris_Gessler,有没有一种可预测的方法来识别字段名?我猜这不是真正意义上的场1,场2。分隔符“;”用于分隔元组中的值以及元组中的值,这使得它很棘手。或者它总是被修饰为字段名,两个值,然后是字段分隔符?字段后面总是跟一个冒号。值后面总是跟一个分号是。。。“奥勒蛮力”的方式。循环。使用C#4.0、Linq、动力学、泛型等。。。必须有一种方法可以将这种可预测的格式反序列化为JSON而不使用循环。我确信有一种方法可以避免循环,但为什么要让它更复杂呢?即使你看不到循环,Linq等的循环仍然存在。我的观点是C#自1.0以来已经走过了很长的路。我相信有一个正则表达式模式可以工作,所以我宁愿使用该解决方案,将JSON字符串反序列化到我的对象。如果我要循环遍历字符串,我可以自己构建对象而无需反序列化。仅供参考:分号拆分会将下一个记录集的字段名添加到第一个记录的末尾。这就是我这么做的原因
var str = "Field1:abc;def;Field2:asd;fgh";
var rows = new List<Dictionary<string, string>>();
int index = 0;
string value;
string fieldname = "";

foreach (var s in str.Split(';'))
{
    if (s.Contains(":"))
    {
        index = 0;
        var tmp = s.Split(':');
        fieldname = tmp[0];
        value = tmp[1];
    }
    else
    {
        value = s;
        index++;
    }

    if (rows.Count < (index + 1))
        rows.Insert(index, new Dictionary<string, string>());

    rows[index][fieldname] = value;
}

var arr = rows.Select(dict => 
                   String.Join("," , dict.Select(kv => 
                       String.Format("\"{0}\":\"{1}\"", kv.Key, kv.Value))))
                   .Select(r => "{" + r + "}");
var json = String.Join(",", arr );
Debug.WriteLine(json);
{"Field1":"abc","Field2":"asd"},{"Field1":"def","Field2":"fgh"}