Строка для последовательности токенов - PullRequest
3 голосов
/ 24 августа 2011

Я анализирую строки последовательности команд, и мне нужно преобразовать каждую строку в строку [], которая будет содержать токены команд в порядке их чтения.

Причина заключается в том, что эти последовательности хранятся в базе данных, чтобы дать команду клиенту протокола выполнить определенную предписанную последовательность для отдельных удаленных приложений. В этих строках есть специальные токены, которые мне нужно добавить в строку [] самостоятельно, потому что они не представляют передаваемые данные; вместо этого они указывают блокирующие паузы.

Последовательности не содержат разделителей. В любой последовательности команд может быть найдено любое количество специальных токенов, поэтому я не могу просто проанализировать строки с помощью регулярных выражений. Кроме того, все эти специальные команды в последовательности заключены в ${}

Вот пример данных, которые мне нужно проанализировать в токены (P1 указывает на паузу блокировки на одну секунду):

"some data to transmit${P1}more data here"

Результирующий массив должен выглядеть следующим образом:

{ "some data to transmit", "${P1}", "more data here" }

Я думаю, что LINQ может помочь с этим, но я не уверен. Единственное решение, которое я могу придумать, - это циклически проходить по каждому символу до тех пор, пока не будет найден $, а затем определить, доступна ли специальная команда паузы, а затем проанализировать последовательность оттуда с помощью индексов.

Ответы [ 3 ]

2 голосов
/ 24 августа 2011

Один из вариантов - использовать Regex.Split(str, @"(\${.*?})") и игнорировать пустые строки, которые вы получаете, когда у вас есть два специальных токена рядом друг с другом.

Возможно, Regex.Split(str, @"(\${.*?})").Where(s => s != "") - это то, что вы хотите.

1 голос
/ 24 августа 2011

Хорошо, так как было упомянуто в комментариях, я предлагаю вам прочитать о лексерах . Они имеют право делать все и даже больше того, что вы описали.

Поскольку ваши требования настолько просты, я скажу, что написать лексер не так уж сложно. Вот какой-то псевдокод, который может это сделать.

IEnumerable<string> tokenize(string str) {

    var result = new List<string>();
    int pos = -1;
    int state = 0;
    int temp = -1;

    while( ++pos < str.Length ) {
        switch(state) {
            case 0:
                if( str[pos] == "$" ) { state = 1; temp = pos; }
                break;
            case 1:
                if( str[pos] == "{" ) { state = 2; } else { state = 0; }
                break;
            case 2:
                if( str[pos] == "}" } {
                    state = 0;
                    result.Add( str.Substring(0, temp) );
                    result.Add( str.Substring(temp, pos) );
                    str = str.Substring(pos);
                    pos = -1;
                }
                break;
            }
    }

    if( str != "" ) {
        result.Add(str);
    }

    return result;
}

Или что-то в этом роде. Обычно я получаю неправильные параметры Substring с первой попытки, но это общая идея.

Вы можете получить гораздо более мощный (и более легкий для чтения) лексер, используя что-то вроде ANTLR .

0 голосов
/ 24 августа 2011

Используя несколько предположений Гейба, я нашел решение, которое делает именно то, что я искал:

string tokenPattern = @"(\${\w{1,4}})";
string cmdSequence = "${P}test${P}${P}test${P}${Cr}";

string[] tokenized = (from token in Regex.Split(cmdSequence, tokenPattern)
                      where token != string.Empty
                      select token).ToArray();

С последовательностью команд в приведенном выше примере массив содержитэто:

{ "${P}", "test", "${P}", "${P}", "test", "${P}", "${Cr}"}
...