2012-07-21 93 views
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]沒有現實的途徑,我被迫使用上述方法來分離字符串,這要求我寫兩次基本相同的代碼。

什麼是我可以解決這個問題的方法,並知道哪個令牌被解析,以便我不必重複我的代碼?

回答

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); 
    } 
} 

..then你可以有一個共同的處理程序,如:

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

你的答案是如此之快和親是StackOverflow的拒絕我接受它作爲另一個3分鐘回答 – l46kok 2012-07-21 04:28:54

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; 
    } 
} 

的例子可以容易地擴展到允許多個令牌解析器如果用於解析每個令牌的邏輯是大不相同。

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); 
} 
+0

嘿,這是一個很好的答案,以及。儘管我認爲正則表達式對於這種簡單的東西可能是一種矯枉過正,但仍然是一個很好的參考。 – l46kok 2012-07-21 04:53:26

+0

你不一定需要在這裏使用正則表達式,你只需要認識到你感興趣的令牌在[方括號]內。只要將這一部分分離出來,無論你可以在那裏工作。正則表達式對此很有效,所以我爲此付出了努力。 – 2012-07-21 04:58:02