Regex.Split()使用(和)作为分隔符,除非用单引号括起来

时间:2014-05-10 00:20:22

标签: c# regex

我有一个输入字符串,如:

  

'lambda''('VARIABLE(','VARIABLE)*')'表达式   (表达式)+

并且需要将它分成由空格,(和)和[和]分隔的标记,除非a(或)被单引号括起来。

我想创建一个正则表达式,用于C#的Regex.Split()方法,该方法将字符串拆分为以下标记:

  

['lambda','(',VARIABLE,(,','VARIABLE,),*,')',EXPRESSION,(,   EXPRESSION,),+]

我之前使用过以下正则表达式:

  

(?= [\(\)\ | \ [\]])|(?< = [\(\)\ | \ [\]])

除了(或)用单引号括起来之外,效果很好,在这种情况下

  

'('

分为

  

[',(,']

非常感谢帮助。

修改

好吧,我现在少了一个问题。这是我最终的解决方案,根本不使用正则表达式:

    private void Scan()
    {
        List<char> accum = new List<char>();

        int index = 0;

        List<string> tokens = new List<string>();

        if (INPUT.Length == 0)
            return;

        while (true)
        {
            if ((index == INPUT.Length) || 
                (
                    (
                     (index == 0 || INPUT[index - 1].ToString() != "'") || 
                     (index == INPUT.Length - 1 || INPUT[index + 1].ToString() != "'") || 
                     (INPUT[index] == ' ')
                    ) 
                    &&
                    (
                     INPUT[index] == ' ' || 
                     INPUT[index] == '(' || 
                     INPUT[index] == ')' || 
                     INPUT[index] == '[' || 
                     INPUT[index] == ']' || 
                     INPUT[index] == '|'
                    )
                )
            )
            {
                string accumulatedToken = string.Join("", accum);
                string currentToken = index < INPUT.Length ? INPUT[index].ToString() : "";
                tokens.Add(accumulatedToken);
                tokens.Add(currentToken);

                CURRENT_TOKEN = tokens.FirstOrDefault(t => !string.IsNullOrWhiteSpace(t));

                INPUT = INPUT.Substring(CURRENT_TOKEN.Length).TrimStart();

                if (CURRENT_TOKEN != null)
                {
                    break;
                }

                index = 0;
            }
            else
            {
                accum.Add(INPUT[index]);
                index++;
            }
        }
    }

1 个答案:

答案 0 :(得分:3)

通过将分隔符放在一个组中,一旦你知道可以split and retain a delimiter,就可以更简单地解决这个问题。

以下模式会产生您提到的输出:

var input = "'lambda' '(' VARIABLE (',' VARIABLE)* ')' EXPRESSION (EXPRESSION)+";
var pattern = @"\s*('[()]'|[()])\s*|[\s[\]]";
var result = Regex.Split(input, pattern);
Console.WriteLine(result);

模式说明:\s*('[()]'|[()])\s*|[\s[\]]

  • \s*('[()]'|[()])\s*
    • \s*:修剪前导/尾随空格(位于两端)
    • ('[()]'|[()]):这整个部分都放在一个组(...)中,因为我们想要拆分中的分隔符,将它们包含在结果中。我们希望将单括号'[()]'和括号中的括号与单引号[()]中的括号匹配。
  • |:替换匹配第一组或下一部分
  • [\s[\]]:拆分空白,[]