标记化中奇怪的regex行为
本文关键字:regex 行为 | 更新日期: 2024-09-19 15:43:03
我正在使用以下正则表达式来标记化:
reg = new Regex("([ ''t{}%$^&*():;_–`,''-''d!'"?'n])");
regex应该稍后过滤掉所有内容,但是我遇到问题的输入字符串格式如下:
; "string1"; "string2"; "string...n";
据我所知,字符串; "social life"; "city life"; "real life"
的结果应该如下所示:
; White " social White life " ; White " city White life " ; White " real White life "
然而,有一个问题,我得到了以下形式的输出
; empty White empty " social White life " empty ; empty White empty " city White life " empty ; empty White empty " real White life " empty
白色:表示空白,empty:表示拆分数组中的空条目。
我的拆分代码如下:
string[] ret = reg.Split(input);
for (int i = 0; i < ret.Length; i++)
{
if (ret[i] == "")
Response.Write("empty<br>");
else
if (ret[i] == " ")
Response.Write("White<br>");
else
Response.Write(ret[i] + "<br>");
}
为什么我收到这些空条目?尤其是当;
后面跟着空间,后面跟着"
时,结果看起来如下:
; empty White empty "
我能得到命令为什么添加空条目的解释吗?以及如何在没有任何额外的O(n)复杂性或使用另一种数据结构如ret
的情况下删除它们
根据我的经验,在regex匹配中进行拆分几乎总是不是最好的主意。通过简单匹配,你会得到更好的结果。
正则表达式非常适合用于标记化目的,因为它们可以让您非常容易地实现状态机,只需看看:
'G(?:
(?<string> "(?>[^"'']+|''.)*" )
| (?<separator> ; )
| (?<whitespace> 's+ )
| (?<invalid> . )
)
演示-当然可以与RegexOptions.IgnorePatternWhitespace
一起使用。
在这里,每个匹配都将具有以下属性:
- 它将从上一场比赛结束时开始,因此不会有不匹配的文本
- 它将包含恰好一个匹配组
- 组的名称告诉您令牌类型
- 您可以忽略
whitespace
组,如果遇到匹配的invalid
组,则应该引发错误
string
组将匹配整个带引号的字符串,它可以处理字符串中的转义,如'"
。
invalid
组应该始终是模式中的最后一个。您可以为其他类型添加规则。
一些示例代码:
var regex = new Regex(@"
'G(?:
(?<string> ""(?>[^""'']+|''.)*"" )
| (?<separator> ; )
| (?<whitespace> 's+ )
| (?<invalid> . )
)
", RegexOptions.IgnorePatternWhitespace);
var input = "; '"social life'"; '"city life'"; '"real life'"";
var groupNames = regex.GetGroupNames().Skip(1).ToList();
foreach (Match match in regex.Matches(input))
{
var groupName = groupNames.Single(name => match.Groups[name].Success);
var group = match.Groups[groupName];
Console.WriteLine("{0}: {1}", groupName, group.Value);
}
这会产生以下内容:
separator: ;
whitespace:
string: "social life"
separator: ;
whitespace:
string: "city life"
separator: ;
whitespace:
string: "real life"
看看处理这些结果比使用拆分容易多少?