2016-03-05 74 views
3

我試圖用this鏈接生成一個在Java中使用的正則表達式。正則表達式問題來解析一個字符串

我可以有以下類型的字符串。

1. customer calls <function_name> using <verb> on <uri> with <object> 
2. customer calls <function_name> using 'POST' on <uri> with <object> 
3. customer calls 'create' using 'POST' on <uri> with <object> 
4. customer calls 'create' using 'POST' on <uri> 

正如你所看到的,with之後的最後部分在我的情況下是可選的。

我實現了下面的正則表達式。

.+call[s]?.+(\'\w+\'|<\w+>).+using.+(\'\w+\'|<\w+>).+on.+(\'\w+\'|<\w+>).*(with.+(\'\w+\'|<\w+>))? 

但是,當我給串3,我得到的輸出作爲'create','POST',<object>, null, null而不是'create','POST',<uri>, <object>。 當我給字符串4時,輸出是'create','POST',<uri>, null, null而不是'create','POST',<uri>

沒有(with.+(\'\w+\'|<\w+>))?正則表達式工作正常字符串4. 我怎樣才能改變這最後一部分,我需要從with可選使部分?

回答

1

由於過度使用貪婪的.+,您的正則表達式會接受太多回溯。請記住,每次編寫.+.*時,正則表達式引擎都會匹配的所有內容,直到行尾,然後需要回溯。這既昂貴又容易出錯 - 它幾乎每次都會吃掉太多的文字,並且在使用這種構造時應該小心非常。它不像大多數人所期望的那樣行事。

在你的情況下,簡單的解決方案是真正說明你期望正是,並從您的示例文本,它看起來像你需要空白,因此就使用\s+代替。您正則表達式變成:

.+?\bcalls?\s+(\'\w+\'|<\w+>)\s+using\s+(\'\w+\'|<\w+>)\s+on\s+(\'\w+\'|<\w+>)(?:\s+with\s+(\'\w+\'|<\w+>))? 

Demo

請注意,我也改變了第一.+的懶惰.+?(即使你很可能只是從模式中刪除它,除非你還需要完整的線被捕獲)後跟一個單詞邊界定位點\b。我也改變了一個小組是非捕捉的,因爲你很可能不需要捕捉它。

1

使用[ ]+代替.+空間

試試這個:

.+call(?:s)?.+(\'\w+\'|<\w+>)[ ]*using.+(\'\w+\'|<\w+>)[ ]*on[ ]*(\'\w+\'|<\w+>)[ ]*(?:with)?[ ]*(\'\w+\'|<\w+>)? 

您將在第4行獲得

1. <function_name> <verb> <uri> <object>  
2. 'create' 'POST' <uri> <object>  
3. <function_name> 'POST' <uri> <object>  
4. 'create' 'POST' <uri> null 

最後一個是null因爲最終令牌(即<object>)缺少

相關問題