我正在为Netduino上运行的.net Micro Framework 4.3开发一个小型网络命令解释器。我使用正则表达式来解析通过流套接字从网络到达的用户输入。命令采用以下格式:
<T1,0,CommandVerb=Payload>
这是设备地址,可以是任何整数的事务ID,命令动词,后跟等号,后跟任何文本。整个事情由尖括号分隔,就像XML标记一样,这有助于解析。
这是我使用的正则表达式:
/*
* Regex matches command strings in format "<Dn,TT,CommandVerb=Payload>
* D is the Device class
* n is the device index
* TT is a numeric transaction ID of at least 1 digits.
* CommandVerb is, obviously, the command verb ;-)
* Payload is optional and is used to supply any parameter values to the command.
*
* N.B. Micro Framework doesn't support named captures and will throw exceptions if they are used.
*/
const string CommandRegex = @"<(\w\d),(\d+),([A-Za-z]\w+)(=((\d+)|(.+)))?>";
static readonly Regex Parser = new Regex(CommandRegex);
此表达式旨在梳理命令的各个部分,以便我可以在代码中轻松访问它们。最后一部分(=((\d+)|(.+)))?
区分数字有效载荷和文本有效载荷,或根本没有有效载荷。
这对我来说效果很好,并且在ReSharper的正则表达式验证器中验证正常。这是我期望得到的输出(我认为这与您从完整的NetFX获得的结果略有不同,我必须通过反复试验来解决这个问题):
/* Command with numeric payload has the following groups
* Group[0] contains [<F1,234,Move=12345>]
* Group[1] contains [F1]
* Group[2] contains [234]
* Group[3] contains [Move]
* Group[4] contains [=12345]
* Group[5] contains [12345]
* Group[6] contains [12345]
* -----
* Command with text payload has the following groups:
* Group[0] contains [<F1,234,Nickname=Fred>]
* Group[1] contains [F1]
* Group[2] contains [234]
* Group[3] contains [Nickname]
* Group[4] contains [=Fred]
* Group[5] contains [Fred]
* Group[7] contains [Fred]
* -----
* Command with verb only (no payload) produces these groups:
* Group[0] contains [<F1,234,Stop>]
* Group[1] contains [F1]
* Group[2] contains [234]
* Group[3] contains [Stop]
*/
......它确实有效。直到我尝试将URL作为有效负载传递的点。一旦我的有效负载字符串中有一个点(。),正则表达式就会中断,我实际上会回到第三种形式,在那里它显然认为根本没有有效负载。举个例子:
<W1,0,HttpPost=http://deathstar.com/route>
我期望得到的是带有文本有效负载的&#39;命令&#39;结果,但我实际得到的是没有有效载荷的&#39;命令&#39;结果。如果我取出点,那么它就像我期望的那样解析,并且我得到了带有文本有效载荷的命令&#39;。一旦我把点放回去,那么(具有讽刺意味).+
似乎不再匹配。
再次注意:这在ReSharper的正则表达式验证程序中正确验证,并且似乎适用于普通的桌面版本&#39;框架按预期方式,但不在.NET Micro Framework中。 Micro Framework正则表达式实现是完整版本的一个子集,但是关于什么应该起作用以及什么不起作用的文档几乎不存在。
我无法理解.+
为何与文字中的点匹配。谁能明白为什么它不起作用?
这是输出:
[Cmd Processor ] Parser matched 8 groups
[Cmd Processor ] Group[0]: <W1,0,HttpPost=http://deat
[Cmd Processor ] Group[1]: W1
[Cmd Processor ] Group[2]: 0
[Cmd Processor ] Group[3]: HttpPost
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
所以Group[4]
不是{null},它为该索引器抛出ArgumentOutOfRangeException
,即使有8个组。此外,Group[0]
被神秘地截断。嗯...
我根据@ Shar1er80:
的回答将此诊断方法添加到我的代码中 [Conditional("DEBUG")]
static void PrintMatches(Match match)
{
if (!match.Success)
{
Dbg.Trace("No match", Source.CommandProcessor);
return;
}
Dbg.Trace("Parser matched "+match.Groups.Count + " groups", Source.CommandProcessor);
for (int i = 0; i < match.Groups.Count; i++)
{
string value;
try
{
var group = match.Groups[i];
value = group == null ? "null group" : group.Value ?? "null value";
}
catch (Exception ex)
{
value = "threw " + ex.GetType() + " " + ex.Message??string.Empty;
}
Dbg.Trace(" Groups[" + i + "]: " + value, Source.CommandProcessor);
}
}
使用<W1,0,HttpPost=http://deathstar.com>
的测试输入,输出为:
[Cmd Processor ] Parser matched 8 groups
[Cmd Processor ] Groups[0]: <W1,0,HttpPost=http://deaths
[Cmd Processor ] Groups[1]: W1
[Cmd Processor ] Groups[2]: 0
[Cmd Processor ] Groups[3]: HttpPost
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
[Cmd Processor ] Groups[4]: threw System.ArgumentOutOfRangeException Exception was thrown: System.ArgumentOutOfRangeException
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
[Cmd Processor ] Groups[5]: threw System.ArgumentOutOfRangeException Exception was thrown: System.ArgumentOutOfRangeException
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
[Cmd Processor ] Groups[6]: threw System.ArgumentOutOfRangeException Exception was thrown: System.ArgumentOutOfRangeException
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
[Cmd Processor ] Groups[7]: threw System.ArgumentOutOfRangeException Exception was thrown: System.ArgumentOutOfRangeException
A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
显然,这是不对的,因为报告了8个匹配但尝试访问有关Groups [3]的任何内容都会引发异常。异常的堆栈跟踪是: System.String ::子串 System.Text.RegularExpressions.Capture ::的get_value TA.NetMF.WeatherServer.CommandParser :: PrintMatches TA.NetMF.WeatherServer.CommandParser :: ParseCommand [剪断]
我对.NET MicroFramework
有opened an issue答案 0 :(得分:1)
Dot匹配一切。 “?(。=((\ d +)|(+)))&gt;” 中 手段 1.创建一个标记表达式(尾部'?'表示它是可选的)。 它必须以等号开头,并包含其中之一 2.1。整数,或 2.2。任何规模的任何东西。
2.2将匹配表达式的其余部分,无论它是什么。
然后,当时间与跟踪结束'&gt;'匹配时,如果跟随'='的结果不是整数,则缓冲区中没有任何内容。 Ergo,没有比赛。
也许您可以尝试使用以下内容代替最后一部分:
“(=([^&GT;] +))&GT;?”。