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]かを比較する現実的な方法がないため、文字列を分離するために上記のアプローチを使用する必要があり、本質的に同じコードを2回記述する必要があります。

この問題を回避し、コードを複製する必要がないように、どのトークンが解析されているかを知る方法は何ですか?

4

3 に答える 3

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 に答える
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 に答える
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 に答える