需要一些正则表达式匹配/替换模式的帮助

时间:2012-02-21 15:15:33

标签: c# regex

我的最终目标是将以下字符串转换为JSON,但我希望通过将fieldname与每个值结合起来让我更近一步。

示例数据:

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+):)*?(?:([^:;]+);)

我能找到的其他一个例子就是做了类似的事情,但只是差异太大,我无法完全理解它。

Regex to repeat a capture across a CDL?

EDIT:

这是我的解决方案。我不会将其作为“解决方案”发布,因为我想赞扬其他人发布的内容。最后,我从每个发布的解决方案中拿出一块,然后想出了这个。感谢所有发布的人。我认为编译,执行最快并且结果最准确的解决方案。

    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));

3 个答案:

答案 0 :(得分:2)

Now you have two problems

我认为正则表达式不是处理此问题的最佳方法。您应该首先分割分号,然后遍历结果,查找以“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

答案 1 :(得分:1)

我会使用RegEx作为解析字符串的最简单,最直接的方式,但是对不起,朋友,我无法想出一个足够聪明的替换字符串来做这一次拍摄。

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

        Regex r = new Regex(@"(?<FieldName>\w+:)*(?:(?<Value>(?:[^:;]+);)+)");

        var matches = r.Matches("Field1:abc;def;Field2:asd;fgh;moo;"); // Modified to test "uneven" data as well.

        var tuples = new[] { new { FieldName = "", Value = "", Index = 0 } }.ToList(); tuples.Clear();

        foreach (Match match in matches)
        {
            var matchGroups = match.Groups;
            var fieldName = matchGroups[1].Captures[0].Value;
            int index = 0;
            foreach (Capture cap in matchGroups[2].Captures)
            {
                var tuple = new { FieldName = fieldName, Value = cap.Value, Index = index };
                tuples.Add(tuple);
                index++;
            }

        }

        var maxIndex = tuples.Max(tup => tup.Index);

        var jsonItemList = new List<string>();

        for (int a = 0; a < maxIndex+1; a++)
        {
            var jsonBuilder = new StringBuilder();
            jsonBuilder.Append("{");

            foreach (var tuple in tuples.Where(tup => tup.Index == a))
            {
                jsonBuilder.Append(string.Format("\"{0}\":\"{1}\",", tuple.FieldName, tuple.Value));
            }
            jsonBuilder.Remove(jsonBuilder.Length - 1, 1); // trim last comma.
            jsonBuilder.Append("}");
            jsonItemList.Add(jsonBuilder.ToString());
        }

        foreach (var item in jsonItemList)
        {
            // Write your items to your document stream.
        }

答案 2 :(得分:1)

我有一个想法,应该可以更短,更清晰的方式做到这一点。它最终没有那么短,你可以质疑它是否更清楚。至少这是解决问题的另一种方法。

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"}