2015-07-19 34 views
2

我正在爲在Netduino上運行的.net Micro Framework 4.3開發一個小型網絡命令解釋器。我使用正則表達式來解析通過流套接字從網絡到達的用戶輸入。命令在以下格式:使用.NET Micro Framework時,爲什麼我的正則表達式匹配失敗?

<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 Micro Framework中。 Micro Framework正則表達式的實現是完整版本的一個子集,但關於什麼應該工作以及什麼不工作的文檔幾乎不存在。

我不明白爲什麼.+不匹配帶點的文本。任何人都可以看到爲什麼它不工作?

更新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個匹配,但試圖訪問任何有關組[3]拋出異常。爲異常堆棧跟蹤爲: System.String ::子串 System.Text.RegularExpressions.Capture ::的get_value TA.NetMF.WeatherServer.CommandParser :: PrintMatches TA.NetMF.WeatherServer.CommandParser :: ParseCommand [剪斷]

opened an issue針對.NET MicroFramework

+3

爲什麼不把'((\ d +)|(。+))'變成'(。+)' –

+1

如果你發現了錯誤或者你使用的是不受支持的正則表達式的一部分。無論哪種方式,你能否將這個問題解決到最低限度?你是說如果你有正則表達式「(。+)」它不會匹配「。」,或者你是否說如果你有((\ d +)|(。+))它不匹配「。」 ?你的正則表達式對我來說似乎沒問題。 –

+0

它似乎是整個最後一部分'(=((\ d +)|(。+)))?'這就是問題所在。我仍然試圖縮小它。這是Group [4]給我的一個問題,當我來研究它的時候它是空的。 –

回答

1

點匹配的一切。 「(=((\ d +)|(。+)))>>」 意味着 1.創建一個帶標記的表達式(尾部'?'表示它是可選的)。 2.它必須以等號開頭,幷包含 2.1。一個整數,或者 2.2。任何大小的東西。

2.2將匹配表達式的其餘部分,不管它是什麼。

然後,當時間與尾部結束'>'匹配時,如果後面的'='不是一個整數,那麼緩衝區中就沒有剩下任何東西了。埃爾戈,沒有匹配。

或許你可以嘗試像,而不是下面的最後一部分:

「(=([^>] +))>?」。

+0

嗯,是不是'。+'不是默認情況下的貪婪?因此它只能匹配下一個字面,不是嗎?無論如何,我是絕望到在這個階段嘗試任何事情,所以我嘗試了它,但它仍然失敗(有趣的是,它沒有看到閉角尖括號)。 –

相關問題