你可以这样做:
var rx = new Regex(@"([\p{L}_][\p{L}\p{N}_]*|[+-]?[0-9]+|==|!=|>=|<=|<<|>>|\|\||&&|[!=+\-*/%{}();]|\s+)*");
Match match = rx.Match(str);
Group g = match.Groups[1];
foreach (var capture in g.Captures)
{
Console.WriteLine(capture);
}
(与您的示例相比,我包含了许多其他运算符)。这仍然是个坏主意。
现在...这仍然是个坏主意,但你可以让它变得更复杂:
string str = @"if(x==0)
{
cout<<x;
var x1 = '\a';
var x2 = '\'';
var x3 = 'X';
var x4 = ""He\""llo\n"";
}";
var fragments = new[]
{
// The order of these pattern is important! Longer patterns should go first (so += before + for example)
new { Name = "Keyword", Pattern = @"(?:if|for|while|var|int|long|string|char|return)\b", Escape = false },
new { Name = "Symbol", Pattern = @"[\p{L}_][\p{L}\p{N}_]*\b", Escape = false },
new { Name = "Number", Pattern = @"[+-]?[0-9]+(?:\.[0-9]+)?\b", Escape = false },
new { Name = "OperatorAssign", Pattern = @"<<=|>>=|&&=|\|\|=|[+\-*/%&|^]=", Escape = false },
new { Name = "Operator", Pattern = @"==|!=|>=|<=|>|<|<<|>>|&&|\|\||[+\-*/%&|^!]", Escape = false },
new { Name = "Space", Pattern = @"\s+", Escape = false },
new { Name = "Assign", Pattern = @"=", Escape = true },
new { Name = "OpenBrace", Pattern = @"{", Escape = true },
new { Name = "CloseBrace", Pattern = @"}", Escape = true },
new { Name = "Semicolon", Pattern = @";", Escape = true },
new { Name = "OpenRoundParenthesis", Pattern = @"(", Escape = true },
new { Name = "CloseRoundParenthesis", Pattern = @")", Escape = true },
new { Name = "OpenSquareParenthesis", Pattern = @"[", Escape = true },
new { Name = "CloseSquareParenthesis", Pattern = @"]", Escape = true },
new { Name = "Char", Pattern = @"'(?:\\.|.)'", Escape = false },
new { Name = "String", Pattern = @"\""(?:\\.|[^""])*""", Escape = false },
};
string allPatterns = string.Join('|', fragments.Select(x => $"(?<{x.Name}>{(x.Escape ? Regex.Escape(x.Pattern) : x.Pattern)})"));
var rx = new Regex(@"\G(?:" + allPatterns + ")");
int ix = 0;
while (ix < str.Length)
{
var match = rx.Match(str, ix);
if (!match.Success)
{
Console.WriteLine($"Error starting at: {str.Substring(ix)}");
break;
}
var group = match.Groups.OfType<Group>().Skip(1).Single(x => x.Success);
string name = group.Name;
string value = match.Value;
if (name != "Space")
{
Console.WriteLine($"Match: {name}: {value}");
}
else
{
Console.WriteLine("Skipping some space");
}
ix += value.Length;
}