拆分一行具有键值对的文本,其中值可以为空

时间:2016-01-05 06:42:56

标签: c# regex

我需要分割一行文字

  1. 交付指令的一般语法是||| name | value || name | value || ... .. |||
  2. 每个交货指令以3个管道字符开始和结束 - |||
  3. 交货指令是由单个管道分隔的一组名称/值对,例如名称|值
  4. 每个名称值对由2个管道字符||
  5. 分隔
  6. 名称和值可能不包含竖线字符
  7. 任何一对的值可以是空字符串。
  8. 我需要一个正则表达式来帮助我解决上述问题。

    我最近尝试使用有限的正则表达式技能:

    string SampleData = "|||env|af245g||mail_idx|39||gen_date|2016/01/03 11:40:06||docm_name|Client Statement (01.03.2015−31.03.2015)||docm_cat_name|Client Statement||docm_type_id|9100||docm_type_name|Client Statement||addr_type_id|1||addr_type_name|Postal address||addr_street_nr|||addr_street_name|Robinson Road||addr_po_box|||addr_po_box_type|||addr_postcode|903334||addr_city|Singapore||addr_state|||addr_country_id|29955||addr_country_name|Singapore||obj_nr|10000023||bp_custr_type|Customer||access_portal|Y||access_library|Y||avsr_team_id|13056||pri_avsr_id|||pri_avsr_name|||ctact_phone|||dlv_type_id|5001||dlv_type_name|Channel to standard mail||ao_id|14387||ao_name|Corp Limited||ao_title|||ao_mob_nr|||ao_email_addr||||??";
    string[] Split = Regex.Matches(SampleData, "(\|\|\|(?:\w+\|\w*\|\|)*\|)").Cast<Match>().Select(m => m.Value).ToArray();
    

    预期输出应如下(基于提供的样本数据字符串):

    1. 的env | af245g
    2. mail_idx | 39
    3. gen_date | 2016/01/03 11:40:06
    4. docm_name |客户声明(01.03.2015-31.03.2015)
    5. docm_cat_name |客户声明
    6. docm_type_id | 9100
    7. docm_type_name |客户声明
    8. addr_type_id | 1
    9. addr_type_name |邮政地址
    10. addr_street_nr |
    11. addr_street_name | Robinson Road
    12. addr_po_box |
    13. addr_po_box_type |
    14. addr_postcode | 903334
    15. addr_city |新加坡
    16. addr_state |
    17. addr_country_id | 29955
    18. addr_country_name |新加坡
    19. obj_nr | 10000023
    20. bp_custr_type |客户
    21. access_portal | Y
    22. access_library | Y
    23. avsr_team_id | 13056
    24. pri_avsr_id |
    25. pri_avsr_name |
    26. ctact_phone |
    27. dlv_type_id | 5001
    28. dlv_type_name |频道标准邮件
    29. ao_id | 14387
    30. ao_name | Corp Limited
    31. ao_title |
    32. ao_mob_nr |
    33. ao_email_addr |

5 个答案:

答案 0 :(得分:6)

您也可以在不使用Regex的情况下执行此操作。它只是简单的分裂。

    string nameValues = "|||zeeshan|1||ali|2||ahsan|3|||";
    string sub = nameValues.Substring(3, nameValues.Length - 6);
    Dictionary<string, string> dic = new Dictionary<string, string>();
    string[] subsub = sub.Split(new string[] {"||"}, StringSplitOptions.None);

    foreach (string item in subsub)
    {
        string[] nameVal = item.Split('|');
        dic.Add(nameVal[0], nameVal[1]);
    }

    foreach (var item in dic)
    {
        // Retrieve key and value here i.e:
        // item.Key
        // item.Value
    }

希望这有帮助。

答案 1 :(得分:2)

(?<=\|\|\|).*?(?=\|\|\|)

您可以使用它来获取key value pairs之间的所有|||。请参阅演示。

https://regex101.com/r/fM9lY3/59

string strRegex = @"(?<=\|\|\|).*?(?=\|\|\|)";
Regex myRegex = new Regex(strRegex, RegexOptions.Multiline);
string strTargetString = @"|||env|af245g||mail_idx|39||gen_date|2016/01/03 11:40:06||docm_name|Client Statement (01.03.2015−31.03.2015)||docm_cat_name|Client Statement||docm_type_id|9100||docm_type_name|Client Statement||addr_type_id|1||addr_type_name|Postal address||addr_street_nr|||addr_street_name|Robinson Road||addr_po_box|||addr_po_box_type|||addr_postcode|903334||addr_city|Singapore||addr_state|||addr_country_id|29955||addr_country_name|Singapore||obj_nr|10000023||bp_custr_type|Customer||access_portal|Y||access_library|Y||avsr_team_id|13056||pri_avsr_id|||pri_avsr_name|||ctact_phone|||dlv_type_id|5001||dlv_type_name|Channel to standard mail||ao_id|14387||ao_name|Corp Limited||ao_title|||ao_mob_nr|||ao_email_addr||||??";

foreach (Match myMatch in myRegex.Matches(strTargetString))
{
   if (myMatch.Success)
   {
     // Add your code here
  }
}

答案 2 :(得分:2)

这是@Syed Muhammad Zeeshan代码的变体,运行得更快:

string nameValues = "|||zeeshan|1||ali|2||ahsan|3|||";
            string[] nameArray = nameValues.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            Dictionary<string, string> dic = new Dictionary<string, string>();
            int i = 0;
            foreach (string item in nameArray)
            {
                if (i < nameArray.Length - 1)
                    dic.Add(nameArray[i], nameArray[i + 1]);
                i = i + 2;
            }

答案 3 :(得分:2)

我认为你让它变得比它需要的更难。这个正则表达式产生了预期的结果:

@"[^|]+\|([^|]*)"

假设您正在处理单一的,格式正确的交付指令,则无需匹配起始和结束三重管道。您也不必担心双管分隔符,因为“name | value”对的“name”部分始终存在。只需查看第一个看起来像带有管道的名称的东西,直到下一个管道字符的所有内容都是值。

答案 4 :(得分:1)

有趣的是,我想尝试一下:

class Program
{
    static void Main(string[] args)
    {
        string nameValueList = "|||zeeshan|1||ali|2||ahsan|3|||";
        while (nameValueList != "|||")
        {
            nameValueList = nameValueList.TrimStart('|');
            string nameValue = GetNameValue(ref nameValueList);
            Console.WriteLine(nameValue);
        }

        Console.ReadLine();
    }

    private static string GetNameValue(ref string nameValues)
    {
        string retVal = string.Empty;
        while(nameValues[0] != '|') // for name
        {
            retVal += nameValues[0];
            nameValues = nameValues.Remove(0, 1);
        }

        retVal += nameValues[0];
        nameValues = nameValues.Remove(0, 1);

        while (nameValues[0] != '|') // for value
        {
            retVal += nameValues[0];
            nameValues = nameValues.Remove(0, 1);
        }

        return retVal;
    }
}

https://dotnetfiddle.net/WRbsRu