在动态分隔符上拆分字符串
String split on dynamic separator
我要处理以下问题。
我必须从通信缓冲区中提取消息。可悲的是,通信协议很糟糕且结构不佳。我想出的区分缓冲区中数据包的唯一方法是服务器传输的中间 "ack" 命令。
示例:
[Packet1][ACK][Packet2][ACK][Packet3]
我本可以使用String.Split(ACK),但分隔符也不一致。但是,有 3 个规则来识别 ack 数据包。
- 以 "AK" 开头。
- 以“0”或“1”结尾。
- 总长度为5个字符。
确认示例:
"AKxxy" 其中:
xx: (01 到 99)
y:(0 或 1)
我希望有一个正则表达式可以解决我的问题,但我缺乏所需的知识和时间。
有没有可能对我有帮助的正则表达式 "expert"?随时提出任何解决方案。
谢谢。
编辑:
示例数据包(我真的不得不删除数据包信息):
AK010机密数据包1AK011机密数据包2AK020AK011机密数据包3AK021机密数据包4AK050
遗憾的是,协议中的每个数据包都没有以特定字符开头或结尾,因此我无法区分它们。为了识别每一个,我必须使用 ack 数据包将它们分开,然后对每一个执行不同的检查。
直接翻译为
\bAK\d{2}[01]\b
也就是
\b # a word boundary
AK # AK literally
\d{2} # two digits
[01] # one of 0 or 1
\b # another word boundary
尽管表达式需要测试(参见 a demo on regex101.com)。
string interim = Regex.Replace(buffer, "AK\d{2}[01]", "|");
var commands = interim.Split('|');
假设 |
不是有效的输入字符。你可以选择一些非常奇特的东西。
编辑:
看看其他答案,这可能只是观赏价值。
@Jan和@ThymosK
的解决方案
var packets = Regex.Split(buffer, @"AK\d{2}[01]");
看起来优雅多了。
但我认为很高兴看到如何将所有解析都移动到正则表达式中。即使它太难读了:P
我设计了一个正则表达式,可以将消息和分隔符分组:
(?s)(AK[0-9][0-9][0,1])|((?:(?!AK[0-9][0-9][0,1]).)*)
它可以像这样分析文本:
你可以测试一下here.
像往常一样,正则表达式是只写的。我自己很难读懂这个。但我会尝试完成它:
第一组很简单,只是捕获你的 ack 命令:
(AK[0-9][0-9][0,1])
第二组包含否定先行 (?! ... )
,它匹配任何未跟随 ...
指定的正则表达式的内容。在这里我们插入您的 ack
语法,所以任何没有跟随 ack
的东西都会被匹配。然后我们添加一个字符,将其扩展为实际匹配 ack
以内的任何内容。
基本上,第二部分断言我们当前没有跟在 ack
之后,然后添加一个字符。尽可能长地重复此操作,直到我们找到 ack
。我把这个变成第二组。
由于我目前没有 C#,因此无法使用 C# 正则表达式引擎将其包装在代码中。但是 python 与它配合得很好,并提供了一个有用的 findall 方法,可以为您提供所有这些组。
我要处理以下问题。 我必须从通信缓冲区中提取消息。可悲的是,通信协议很糟糕且结构不佳。我想出的区分缓冲区中数据包的唯一方法是服务器传输的中间 "ack" 命令。
示例:
[Packet1][ACK][Packet2][ACK][Packet3]
我本可以使用String.Split(ACK),但分隔符也不一致。但是,有 3 个规则来识别 ack 数据包。
- 以 "AK" 开头。
- 以“0”或“1”结尾。
- 总长度为5个字符。
确认示例:
"AKxxy" 其中:
xx: (01 到 99)
y:(0 或 1)
我希望有一个正则表达式可以解决我的问题,但我缺乏所需的知识和时间。
有没有可能对我有帮助的正则表达式 "expert"?随时提出任何解决方案。
谢谢。
编辑:
示例数据包(我真的不得不删除数据包信息):
AK010机密数据包1AK011机密数据包2AK020AK011机密数据包3AK021机密数据包4AK050
遗憾的是,协议中的每个数据包都没有以特定字符开头或结尾,因此我无法区分它们。为了识别每一个,我必须使用 ack 数据包将它们分开,然后对每一个执行不同的检查。
直接翻译为
\bAK\d{2}[01]\b
也就是
\b # a word boundary
AK # AK literally
\d{2} # two digits
[01] # one of 0 or 1
\b # another word boundary
尽管表达式需要测试(参见 a demo on regex101.com)。
string interim = Regex.Replace(buffer, "AK\d{2}[01]", "|");
var commands = interim.Split('|');
假设 |
不是有效的输入字符。你可以选择一些非常奇特的东西。
编辑:
看看其他答案,这可能只是观赏价值。 @Jan和@ThymosK
的解决方案var packets = Regex.Split(buffer, @"AK\d{2}[01]");
看起来优雅多了。
但我认为很高兴看到如何将所有解析都移动到正则表达式中。即使它太难读了:P
我设计了一个正则表达式,可以将消息和分隔符分组:
(?s)(AK[0-9][0-9][0,1])|((?:(?!AK[0-9][0-9][0,1]).)*)
它可以像这样分析文本:
你可以测试一下here.
像往常一样,正则表达式是只写的。我自己很难读懂这个。但我会尝试完成它:
第一组很简单,只是捕获你的 ack 命令:
(AK[0-9][0-9][0,1])
第二组包含否定先行 (?! ... )
,它匹配任何未跟随 ...
指定的正则表达式的内容。在这里我们插入您的 ack
语法,所以任何没有跟随 ack
的东西都会被匹配。然后我们添加一个字符,将其扩展为实际匹配 ack
以内的任何内容。
基本上,第二部分断言我们当前没有跟在 ack
之后,然后添加一个字符。尽可能长地重复此操作,直到我们找到 ack
。我把这个变成第二组。
由于我目前没有 C#,因此无法使用 C# 正则表达式引擎将其包装在代码中。但是 python 与它配合得很好,并提供了一个有用的 findall 方法,可以为您提供所有这些组。