使用.net微框架,为什么我的正则表达式匹配失败
本文关键字:正则表达式 失败 我的 为什么 net 框架 使用 | 更新日期: 2023-09-27 18:03:22
我正在为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的正则表达式验证器中验证OK。以下是我期望得到的输出(我认为这与您从完整的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>
我期望得到的是"带有文本有效载荷的命令"结果,但我实际得到的是"没有有效载荷的命令"结果。如果我拿出点,然后它解析我所期望的,我得到'命令与文本有效载荷'。一旦我把点放回去,那么(讽刺的是).+
似乎不再匹配。
再次注意:这在ReSharper的正则表达式验证器中可以正确验证,并且在正常的"桌面"框架中也能正常工作,但在。net微框架中却不能。微框架regex实现是完整版本的一个子集,但是关于什么应该工作,什么不应该工作的文档几乎不存在。
我不明白为什么.+
不匹配文本中有一个点。有人知道为什么不行吗?
UPDATE 1 -添加诊断
输出如下:
[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]
是空的,它抛出一个ArgumentOutOfRangeException
为该索引器,即使有8组。而且,Group[0]
被神秘地截断了。嗯…
更新2 -改进了诊断
我根据@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.Text.RegularExpressions.Capture: get_ValueTA.NetMF.WeatherServer.CommandParser: PrintMatchesTA.NetMF.WeatherServer.CommandParser: ParseCommand(剪)
我已经打开了一个针对。net MicroFramework的问题
点匹配所有内容。"(= ((' d +)|(.+)))?>"意味着1. 创建一个带标签的表达式(后面的'?’意思是可选的)。2. 它必须以等号开头,并且包含任意一个2.1. 整数,或者2.2. 任何东西,任何大小
2.2将匹配表达式的其余部分,无论它是什么。
然后,当匹配末尾结束的'>'时,如果'='后面的不是整数,则缓冲区中没有任何剩余。因此,不匹配。
也许你可以尝试下面的内容来代替最后一部分:
"(=([^>]+))?>".