2014-09-19 3 views
0

Мне нужно разобрать проприетарную строку с сервера tcp. строки я получаю следующее:Parse proprietary returnstring из сервера

!re.tag=3=.id=*1=name=1 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~!re.tag=3=.id=*2=name=3 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~!done.tag=3~ 

Так что, когда чередование от в done.tag .... и Деление строки на ~ я могу сломать (в данном случае) два объекта

!re.tag=3=.id=*1=name=1 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~ 
!re.tag=3=.id=*2=name=3 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~ 

then im сталкивается с проблемой, как разделить свойства и их значения.

!re.tag=3 
=.id=*2 
=name=3 Hour 
=owner=admin 
=name-for-users= 
=validity=3h 
=starts-at=logon 
=price=0 
=override-shared-users=off 

Обычно я буду делать раскол на знак равенства, как это:

List<string> arProfiles = profilString.Split('=').ToList(); 

и тогда я могу предположить, что значение «имя» свойство находится в положении 5 (!) .

есть ли более правильный способ для разбора такого рода строк (этот в то время как я буду получать такие же строки из разных функций)

Пола

+2

Почему вы угадать? У вас нет документации для того, что означает эта строка и как она структурирована? –

+1

Я хотел бы сделать комплимент создателю этой проприетарной строки формата – InferOn

+0

@ LasseV.Karlsen Я предполагаю, что создатель этого формата изменил что-то в последней версии прошивки, а затем мой код больше не работал (они добавили еще один equals sign, в прошлом значение Name было в позиции 4) –

ответ

4
//so. we've got the response here 
var response = "!re.tag=3=.id=*1=name=1 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~!re.tag=3=.id=*2=name=3 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~!done.tag=3~"; 

// first we split the line into sections 
var sections = Regex.Matches(response, @"!(?<set>.*?)~").Cast<Match>().Select(s=>s.Groups["set"].Value).ToArray(); 

// next we can parse any section into key/value pairs 
var parsed = Regex.Matches(sections[0], @"(?<key>.*?)=(?<value>[^=]*)=?").Cast<Match>() 
    .Select(pair => new 
    { 
     key = pair.Groups["key"].Value, 
     value = pair.Groups["value"].Value, 
    }).ToArray(); 

Не забудьте

using System.Text.RegularExpressions; 
+0

Спасибо @mad Sorcerer, что вы настоящий мастер RegEx. –

+0

Это изящное решение, но, как вы можете видеть в ответ, есть ключи, которые встречаются более одного раза (id, name и т. Д.). Я предполагаю, что они представляют две записи, и эти два разделены символом ~. Вы должны разбить строку среди символа ~, а затем использовать регулярное выражение для каждого. Автором этого проприетарного формата ответа должен быть, по меньшей мере, недопонятый гений. – Bedford

+0

@Bedfold есть переменная 'sections', в которой содержатся отдельные записи, поэтому каждый ключ уникален в каждом секте. –

0

Каждое имя параметра начинается и заканчивается символом '='. Это означает, что вам нужно обработать строку, ища первое значение между двумя «=». Это произойдет после этого, и перед следующим символом «=» или концом строки будет значение этого свойства. Свойство может иметь пустое значение, поэтому его также нужно обработать.

Первая часть строки отличается:

!re.tag=3 

Вы должны удалить или обработать его отдельно.

способ разобрать было бы:

var inString = @"=.id=*1=name=1 Hour=owner=admin=name-for-users==validity=3h=starts-at=logon=price=0=override-shared-users=off~"; 

     int startOfParameterName = 0; 
     int endOfParameterName = 0; 
     int startOfParameterValue = 0; 

     bool paramerNameEndFound = false; 
     bool paramerNameStartFound = false; 

     var arProfiles = new Dictionary<string, string>(); 

     for(int index = 0; index < inString.Length; index++) 
     { 
      if (inString[index] == '=' || index == inString.Length - 1) 
      { 
       if (paramerNameEndFound || index == inString.Length - 1) 
       { 
        var parameterName = inString.Substring(startOfParameterName, endOfParameterName - startOfParameterName); 
        var parameterValue = startOfParameterValue == index ? string.Empty : inString.Substring(startOfParameterValue, index - startOfParameterValue); 

        arProfiles.Add(parameterName, parameterValue); 

        startOfParameterName = index + 1; 
        paramerNameEndFound = false; 
        paramerNameStartFound = true; 
       } 
       else 
       { 
        if (paramerNameStartFound == false) 
        { 
         paramerNameStartFound = true; 
         startOfParameterName = index + 1; 
        } 
        else 
        { 
         paramerNameEndFound = true; 
         endOfParameterName = index; 
         startOfParameterValue = index + 1; 
        } 
       } 

      } 
     } 

Где находится комната до совершенства, но это работает!

+0

Большое вам спасибо за ваше решение! Я не возьму твою, но снова спасибо! –

0

Похоже каждый из значений (не имена параметров) окружены парой "=".

Это должно дать вам то, что вы хотите, более или менее:

var input = "!re.tag=3=.id=*1=name=1 Hour=(...etc...)"; 

Dictionary<string, string> values = new Dictionary<string, string>(); 

while(input.Count() > 0){ 
    var keyChars = input.TakeWhile(x=> x != '='); 
    var currTag = new string(keyChars.ToArray()); 

    var valueChars = input.Skip(currTag.Count() + 1).TakeWhile(x=> x != '='); 
    var value = new string(valueChars.ToArray()); 

    values.Add(currTag, value); 
    input = new string(input.Skip(currTag.Length + value.Lenght + 2) 
          .ToArray()); 
} 

Это приводит следующие ключи и значения:

!re.tag    | 3 
.id     | *1 
name     | 1 Hour 
owner     | admin 
name-for-users  | 
validity    | 3h 
starts-at    | logon 
price     | 0 
override-shared-users | off~ 
+0

thanx для этого решения! Я не возьму твою, но снова спасибо! –

Смежные вопросы