使用String Split区分正在解析的字符串

时间:2012-07-21 04:16:58

标签: c# .net string parsing token

我需要解析一条格式如下的行:

s = "Jun 21 09:47:50 ez-x5 user.debug if_comm: [TX] 02 30 20 0f 30 31 39 24 64 31 30 31 03 54 ";

我正在用[TX]或[RX]分割线。以下是我对解析后的字符串的处理方法:

s = "Jun 21 09:47:50 ez-x5 user.debug if_comm: [TX] 02 30 20 0f 30 31 39 24 64 31 30 31 03 54 ";
string[] stringSeparators = new string[] { "[TX] " + start_key };
string transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
//At this point, transfer[] = 02 30 20 0f 30 31 39 24 64 31 30 31 03 54
if (!string.IsNullOrEmpty(transfer))
{
    string key = ""; 
    string[] split = transfer.Split(' ');
    if (split[0] == start_key)
    {
        for (int i = 0; i < key_length; i++)
        {
            key += split[i + Convert.ToInt32(key_index)];
        }
        TX_Handle(key);
    }
}

stringSeparators = new string[] { "[RX]" + start_key };
transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
if (!string.IsNullOrEmpty(transfer))
{
    string key = "";
    string[] split = transfer.Split(' ');
    if (split[0] == start_key)
    {
        for (int i = 0; i < key_length; i++)
        {
            key += split[i + Convert.ToInt32(key_index)];
        }
        RX_Handle(key);
    }
}

基本上,因为我没有现实的方法来比较给定的令牌是[TX]还是[RX],我被迫使用上面的方法来分离字符串,这要求我基本上编写两次相同的代码。

有什么方法可以解决这个问题并知道正在解析哪个令牌,以便我不必复制我的代码?

3 个答案:

答案 0 :(得分:1)

这样做的最好方法是看看什么是常见的。您的代码中常见的是什么?基于2个不同的令牌和基于2个不同令牌的函数调用进行拆分。这可以分解为条件,那么,为什么不将公共元素移动到条件?

const string receiveToken = "[RX] ";
const string transmitToken = "[TX] ";

string token = s.IndexOf(receiveToken) > -1 ? receiveToken  : transmitToken;

..现在你有了你的令牌,所以你可以删除大部分重复。

stringSeparators = new string[] { token + start_key };
transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
if (!string.IsNullOrEmpty(transfer))
{
    string key = "";
    string[] split = transfer.Split(' ');
    if (split[0] == start_key)
    {
        for (int i = 0; i < key_length; i++)
        {
            key += split[i + Convert.ToInt32(key_index)];
        }
        RX_TX_Handle(key, token);
    }
}

..那么你可以拥有一个通用的处理程序,例如:

void RX_TX_Handle(string key, string token)
{
    token == receiveToken ? RX_Handle(key) : TX_Handle(key);
}

答案 1 :(得分:1)

如何使用不同的方法并使用正则表达式。混合一点LINQ,你有一些很容易遵循的代码。

static void ParseLine(
    string line,
    int keyIndex,
    int keyLength,
    Action<List<byte>> txHandler,
    Action<List<byte>> rxHandler)
{
    var re = new Regex(@"\[(TX|RX)\](?: ([0-9a-f]{2}))+");
    var match = re.Match(line);
    if (match.Success)
    {
        var mode = match.Groups[1].Value; // either TX or RX
        var values = match.Groups[2]
            .Captures.Cast<Capture>()
            .Skip(keyIndex)
            .Take(keyLength)
            .Select(c => Convert.ToByte(c.Value, 16))
            .ToList();
        if (mode == "TX") txHandler(values);
        else if (mode == "RX") rxHandler(values);
    }
}

或没有正则表达式:

static void ParseLine(
    string line,
    int keyIndex,
    int keyLength,
    Action<List<byte>> txHandler,
    Action<List<byte>> rxHandler)
{
    var start = line.IndexOf('[');
    var end = line.IndexOf(']', start);
    var mode = line.Substring(start + 1, end - start - 1);
    var values = line.Substring(end + 1)
        .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
        .Skip(keyIndex)
        .Take(keyLength)
        .Select(s => Convert.ToByte(s, 16))
        .ToList();
    if (mode == "TX") txHandler(values);
    else if (mode == "RX") rxHandler(values);
}

答案 2 :(得分:0)

我不是百分百肯定如果这回答了你的问题,但我会创建一个负责解析令牌的TokenParser类。您会发现单元测试更容易。

public enum TokenType
{
    Unknown = 0,
    Tx = 1,
    Rx = 2
}

public class Token
{
    public TokenType TokenType { get; set; }
    public IEnumerable<string> Values { get; set; }
}

public class TokenParser
{
    public Token ParseToken(string input)
    {
        if (string.IsNullOrWhiteSpace(input)) throw new ArgumentNullException("input");

        var token = new Token { TokenType = TokenType.Unknown };

        input = input.ToUpperInvariant();
        if (input.Contains("[TX]"))
        {
            token.TokenType = TokenType.Tx;
        }
        if (input.Contains("[RX]"))
        {
            token.TokenType = TokenType.Rx;
        }

        input = input.Substring(input.LastIndexOf("]", System.StringComparison.Ordinal) + 1);
        token.Values = input.Trim().Split(Convert.ToChar(" "));

        return token;
    }
}

如果解析每个令牌的逻辑差别很大,那么可以轻松扩展该示例以允许多个令牌解析器。