为了在接下来的几章中探索一些特性,我们需要通过增加一些特性来改进我们的 regex tester 程序。虽然最初的程序很适合测试搜索模式,但我们将在接下来的几章中探索分组和捕获、查找和优化,因此我们需要创建一个新的增强版本的测试应用程序。
您可以在https://bitbucket.org/syncfusiontech/regularexpressions下载完整的应用程序。请务必下载该应用程序或自己创建它,以帮助探索本书的其余章节。
图 4:正则表达式测试器
我们正在添加的功能之一是能够报告引擎处理正则表达式需要多长时间。我们将使用系统中的秒表类。诊断装配。这允许我们报告表达式处理的毫秒数。
private void RunBtn_Click(object sender, EventArgs e)
{
Stopwatch stopWatch = new Stopwatch(); // Create a high resolution time.
// Start the timer.
stopWatch.Start();
// Process the expression.
// Record how long the processing took.
stopWatch.Stop();
TimeSpan HowLong = stopWatch.Elapsed;
Double TotalTicks = HowLong.TotalMilliseconds;
TimeLabel.Text = TotalTicks.ToString("F3") + " ms";
}
这将允许我们尝试各种优化,以使我们的正则表达式运行得更快。对于我们到目前为止看到的大多数例子,您可能不会注意到有什么不同。但是,如果您正在处理大量的大型文本输入,额外压缩几毫秒就可以了。
我们还添加了一个复选框来清除 regex 缓存。这将允许您提前测试编译正则表达式的影响,这对于将在代码中重复使用的正则表达式模式来说是一个特别有用的优化。清除缓存的代码如下所示:
if (clearCache.Checked)
{
Regex.CacheSize=0;
clearCache.Checked = false;
}
在下一章中,我们将探索组如何在正则表达式中工作。通过向我们的测试应用程序添加树视图组件,我们可以看到在处理表达式时找到的组。用组和捕获填充树视图的代码如下所示:
rootNode.Add(TV.Nodes.Add("[ "+theMatch.Value+" ]"));
TreeIndex++;
foreach (string groupName in theExpr.GetGroupNames())
{
Group theGroup = theMatch.Groups[groupName];
if (groupName != "0")
{
TreeNode ChildNode = rootNode[TreeIndex].Nodes.Add("<" + groupName + "> (" + theGroup + ")");
{
ChildNode.Nodes.Add(theCapture.Value);
}
}
}
最后,我们将为所有正则表达式选项提供复选框,而不仅仅是我们在前面章节中介绍的子集。
private void RunBtn_Click(object sender, EventArgs e)
{
Boolean isGlobal = false;
RegexOptions theOpts = RegexOptions.None;
foreach (var item in CB.CheckedItems)
{
if (item.ToString().ToLower() == "global") { isGlobal = true; }
if (item.ToString().ToLower() == "multiline")
{ theOpts = theOpts | RegexOptions.Multiline; }
if (item.ToString().ToLower() == "ignore case")
{ theOpts = theOpts | RegexOptions.IgnoreCase; }
if (item.ToString().ToLower() == "singleline")
{ theOpts = theOpts | RegexOptions.Singleline; }
if (item.ToString().ToLower() == "compiled")
{ theOpts = theOpts | RegexOptions.Compiled; }
if (item.ToString().ToLower() == "ignorepatternwhitespace")
{ theOpts = theOpts | RegexOptions.IgnorePatternWhitespace; }
if (item.ToString().ToLower() == "righttoleft")
{ theOpts = theOpts | RegexOptions.RightToLeft;}
if (item.ToString().ToLower() == "emcascript")
{ theOpts = theOpts | RegexOptions.ECMAScript; }
if (item.ToString().ToLower() == "cultureinvariant")
{ theOpts = theOpts | RegexOptions.CultureInvariant; }
}
单击匹配按钮时,在设置选项后会执行以下代码:
// Start the timer.
stopWatch.Start();
List<TreeNode> rootNode = new List<TreeNode>();
int TreeIndex = -1;
// If global, then iterate the Matches collection.
if (isGlobal)
{
try
{
Regex theExpr = new Regex(pattern,theOpts);
foreach (Match match in theExpr.Matches(source))
{
int endindex = match.Length;
rtb.Select(match.Index, endindex);
rtb.SelectionBackColor = BGHighlight;
rtb.SelectionColor = FGHighlight;
rootNode.Add(TV.Nodes.Add("[ " + match.Value + " ]"));
TreeIndex++;
foreach (string groupName in theExpr.GetGroupNames())
{
Group theGroup = match.Groups[groupName];
if (groupName != "0")
{
TreeNode ChildNode = rootNode[TreeIndex].Nodes.Add("<" + groupName + "> (" + theGroup + ")");
foreach (Capture theCapture in theGroup.Captures)
{
ChildNode.Nodes.Add(theCapture.Value);
}
}
}
}
}
catch (Exception ex)
{
SLAB.Text = ex.Message;
}
}
else
{
try
{
Regex theExpr = new Regex(pattern, theOpts);
Match theMatch = theExpr.Match(source);
if (theMatch.Success)
{
int endindex = theMatch.Length;
rtb.Select(theMatch.Index, endindex);
rtb.SelectionBackColor = BGHighlight;
rtb.SelectionColor = FGHighlight;
rootNode.Add(TV.Nodes.Add("[ "+theMatch.Value+" ]"));
TreeIndex++;
foreach (string groupName in theExpr.GetGroupNames())
{
Group theGroup = theMatch.Groups[groupName];
if (groupName != "0")
{
TreeNode ChildNode = rootNode[TreeIndex].Nodes.Add("<" + groupName + "> (" + theGroup + ")");
foreach (Capture theCapture in theGroup.Captures)
{
ChildNode.Nodes.Add(theCapture.Value);
}
}
}
}
else
{
SLAB.Text = "Not found...";
}
}
catch (Exception ex)
{
SLAB.Text = ex.Message;
}
}
TV.ExpandAll();
我们需要做的改变之一是创建一个 regex 对象,而不是依赖静态的 Regex 类。这是因为某些组功能,即 GetGroupnames(),不能作为静态正则表达式方法使用。