1

我需要解析类似于以下格式的行:

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],我不得不使用上述方法来分隔字符串,这需要我编写两次基本相同的代码。

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

4

3 回答 3

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);
}
于 2012-07-21T04:25:04.910 回答
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);
}
于 2012-07-21T04:42:01.657 回答
0

我不能 100% 确定这是否能回答您的问题,但我会创建一个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;
    }
}

如果解析每个令牌的逻辑大不相同,则可以轻松扩展该示例以允许多个令牌解析器。

于 2012-07-21T04:31:30.260 回答