这不是正则表达式,而是一个基本的分词器,可能很有效(注意,您不需要做string.Join
- 您可以通过foreach
使用IEnumerable<string>
):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
static class Program
{
static void Main()
{
string recombined = string.Join(" ", Tokenize("(x+3>5*y)&&(z>=3 || k!=x)"));
}
public static IEnumerable<string> Tokenize(string input)
{
var buffer = new StringBuilder();
foreach (char c in input)
{
if (char.IsWhiteSpace(c))
{
if (buffer.Length > 0)
{
yield return Flush(buffer);
}
continue;
}
if (IsOperatorChar(c))
{
if (buffer.Length > 0)
{
if (!CanCombine(buffer, c))
{
yield return Flush(buffer);
}
}
buffer.Append(c);
continue;
}
if (buffer.Length > 0 && IsOperatorChar(buffer[0]))
{
yield return Flush(buffer);
}
buffer.Append(c);
}
if (buffer.Length != 0)
yield return Flush(buffer);
}
static string Flush(StringBuilder buffer)
{
string s = buffer.ToString();
buffer.Clear();
return s;
}
static readonly string[] operators = { "+", "-", "*", "/", "%", "=", "&&", "||", "==", ">=", ">", "<", "<=", "!=", "(",")" };
static readonly char[] opChars = operators.SelectMany(x => x.ToCharArray()).Distinct().ToArray();
static bool IsOperatorChar(char newChar)
{
return Array.IndexOf(opChars, newChar) >= 0;
}
static bool CanCombine(StringBuilder buffer, char c)
{
foreach (var op in operators)
{
if (op.Length <= buffer.Length) continue;
bool startsWith = true;
for (int i = 0; i < buffer.Length; i++)
{
if (op[i] != buffer[i])
{
startsWith = false;
break;
}
}
if (startsWith && op[buffer.Length] == c) return true;
}
return false;
}
}
<
作为一个标记产生,直到下一个字符被读取,这样您就知道它不是<=
),然后使用逆波兰算法创建一个语法树。 - Marc Gravell"(x+3>5*y)&&(z>=3 || k!=x)".replaceAll("==?|>=?|<=?|!=|&&|\\|\\||[-()+*/%]", " $0 ").replaceAll(" {2,}", " ").trim()
。如果这足够的话,我相信你可以将其转换为 C#。 - Bernhard Barker