我需要解析一条格式如下的行:
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],我被迫使用上面的方法来分离字符串,这要求我基本上编写两次相同的代码。
有什么方法可以解决这个问题并知道正在解析哪个令牌,以便我不必复制我的代码?
答案 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;
}
}
如果解析每个令牌的逻辑差别很大,那么可以轻松扩展该示例以允许多个令牌解析器。