2017-06-13 112 views
-3

我要解析的形式正則表達式:處理參數

(<paramID><paramValue>)*(LastValue)* 

其中芳族聚酰胺是參數的ID和paramValue幾乎任何不不包含潛在的芳族聚酰胺的一些文本(所以我們可以毫不含糊地解析它)。

需要注意的主要事情是:

  1. 第一芳族聚酰胺是可選的。
  2. paramValues可以使用分組。分組內的任何內容都被視爲一個令牌,甚至可能是paramID。
  3. 每個paramValue都會被貪婪地解析,除了最​​後一個,它會被懶惰地解析。 (我知道這使得相同參數的不同順序有不同的解釋,但本身總是明確界定,並容易解釋明白)

芳族聚酰胺= "\s-[^\s\[\(\{\\""]+" paramValue =基本上是在芳族聚酰胺的之間。由於這可能包含諸如paramID之類的內容,但由於它們位於「組」之內,因此需要忽略它們。

例如,

First Param Value -p1 Second Param Value -p2[Third-Param-Value] -X "-Fourth -Param -Value" -pl LastParamValue Last Value 

應在明顯的方式進行解析。

+0

這是什麼問題? –

+0

@ShaiCohen這不是很明顯嗎?我需要一個正則表達式來做到這一點。 – AbstractDissonance

回答

1

我建議來標記表達如下:

  • 組的括號內。
    • 使用balanced groups對於[...],您可能會得到類似(?>(?'o'\[)[^][]*)+(?>[^][]*(?'-o'\]))+的東西。這允許組嵌套。
    • 類似的表述可爲{...}(...)
  • 組用引號生產(可能內轉義引號)
  • 參數名稱以空格前面有一個破折號
  • 和值部分作爲系列由空格包圍的非空格字符。這些以後會連接所有參數,但最後一個。對於最後一個參數,只有第一個值將被採用,而其他參數將構成最後一個值。

所以記號賦予表達式爲:

(?x) 
    \s*(?<token> (?>(?'o'\[)[^][]*)+(?>[^][]*(?'-o'\]))+)\s* # balanced [...] group 
| \s*(?<token> (?>(?'o'\{)[^{}]*)+(?>[^{}]*(?'-o'\}))+)\s* # balanced {...} group 
| \s*(?<token> (?>(?'o'\()[^()]*)+(?>[^()]*(?'-o'\)))+)\s* # balanced (...) group 
| \s*(?<token> "(?:\\"|[^"])*")\s* # quoted group with possible escaped quotes within 
| \s*(?<token> -[^\s"({[]+)   # parameter name 
| (?<token> \s*\S+\s*)    # parameter value part not in group/quotes 

Demo

然後我們需要通過令牌來掃描,並適當地收集參數值對:​​

var paramDict = new Dictionary<string, string>(); 
var currParam = "<FIRST>"; 
var currValues = new List<string>(); 
var lastParam = currParam; 
foreach (var token in tokensRegex.Matches(expression) 
    .Cast<Match>().Select(m => m.Groups["token"].Value)) 
{ 
    if (token.StartsWith("-")) 
    { 
     // This is a paramater name. Store collected value 
     // for the previous one and reset currXXX 
     if (currParam == "<FIRST>" && currValues.Count == 0) 
     { 
      // The first param has its own name so don't add the default one. 
      // Set the param name only 
      currParam = token; 
     } 
     else 
     { 
      paramDict.Add(currParam, string.Join("", currValues)); 
      currParam = token; 
      currValues = new List<string>(); 
     } 
    } 
    else 
    { 
     currValues.Add(token); 
    } 
} 

// If the last value list has more that one item, set the first item 
// as the last param value and the rest as the last value. 
if (currValues.Count > 1) 
{ 
    paramDict[currParam] = currValues[0]; 
    paramDict["<LAST>"] = string.Join("", currValues.Skip(1)); 
} 

演示:https://dotnetfiddle.net/bg1jxp