2017-06-13 150 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