RegEx Tester - 正则表达式测试器






4.98/5 (60投票s)
它能帮助您开发并充分测试正则表达式在目标文本中的匹配情况。

引言
使用 RegEx Tester,您可以充分开发和测试正则表达式在目标文本中的匹配情况。
它的用户界面旨在帮助您进行正则表达式开发;特别是那些庞大而复杂的正则表达式。
它使用并支持.NET RegEx
类中几乎所有可用的功能。
关于本文的撰写,我必须告诉您,英语不是我的母语,我在编辑、语法和拼写方面已尽力而为。您可能会发现写作错误,请告诉我,以便我进行更正。
功能列表
如果您有新的功能想法,可以将其编写出来,然后通过电子邮件发送给我,我将添加并注明您的贡献。如果您不知道如何正确实现这个想法,请在评论区发表,其他人(或我)可能会帮助您完成。让我们一起协作。
- 异步执行,使用户能够中止执行。即使您创建了一个 灾难性回溯 的混乱。[作者:Pablo Oses]
- 缩进输入模式,在执行前会去除 \r \n \t \v 和空格。这允许您以缩进和分格子的方式编写那些丑陋、冗长且晦涩的正则表达式。[作者:Pablo Oses]
- 替换模式,启用
RegEx.Replace()
函数的使用。[作者:Pablo Oses] - Mono 兼容,使其能够在 Linux 上运行。[作者:Pablo Oses]
- 测试文本高亮显示,基于结果选择。[作者:Davide Mauri]
- F5 热键,无需改变光标位置或选择即可运行测试。摆脱鼠标![作者:Pablo Oses]
- 匹配项列表,显示位置、长度以及匿名或命名捕获组。[作者:Davide Mauri 和 Pablo Oses]
- 一个“复制到剪贴板”按钮,可选择“C# 代码片段”、“C# 转义
字符串
”、“HTML 编码”或“纯文本”模式。[作者:Kurt Griffiths 和 Pablo Oses] - 调整窗口的三个部分(正则表达式、文本和结果)的大小。[作者:Pablo Oses]
- 忽略大小写、多行、单行和区域设置不变选项。[作者:Davide Mauri 和 Pablo Oses]
- 窗口大小调整和最大化功能。[作者:Kurt Griffiths 和 Pablo Oses]
- 快速链接到正则表达式库和 ILoveJackDaniels 的备忘单。[作者:Pablo Oses]
- 在测试文本中查找功能。[作者:Pablo Oses]
- 执行时间测量。[作者:Pablo Oses]
这个程序有什么特别之处?
正如 balazs_hideghety 在他的评论中所说,市面上还有其他流行且出色的程序,如 RegEx buddy 或 Expresso,它们功能强大,似乎是正则表达式开发和测试的终极选择,但我仍然使用这个工具。为什么?我需要一个工具来帮助我设计 HTML 提取正则表达式。例如(截至 2009 年 5 月),如果您评估以下内容...
<td class="Frm_MsgSubject"><[^>]*?>(?<title>.*?)</a>.*?
<td class="Frm_MsgAuthor"><[^>]*?>(?<author>.*?)</a>.*?
<td class="Frm_MsgDate"[^>]*?>(?<date>.*?)&.*?
<td class="MsgBd BdSel ">.*?<td colspan="2">(?<body>[^<]*?)<"
...针对此页面的 HTML 源代码,您只需一次操作即可解析并提取页面中的所有评论及其相应的标题、正文、日期、用户等信息。当您从真实网站提取数据时,正则表达式非常强大。但问题是,所需的正则表达式非常长且极其晦涩难懂。您确实需要一些空格和缩进来使其清晰易懂,并且需要一个大窗口,提供足够的空间,以及一个能够处理大型原始 HTML 文档的测试文本框,这时这个工具就显得非常有用。
我在 RegExTester
中开发同样的正则表达式时,看起来是这样的。
<td\sclass="Frm_MsgSubject"> <[^>]*? > (?<title>.*?) </a>
.*?
<td\sclass="Frm_MsgAuthor"> <[^>]*? > (?<author>.*?) </a>
.*?
<td\sclass="Frm_MsgDate" [^>]*? > (?<date>.*?) &
.*?
<td\sclass="MsgBd\sBdSel\s"> .*? <td\scolspan="2"> (?<body>[^<]*?) <
正如您所见,我认为这种丑陋的正则表达式开发辅助工具是这个程序的核心功能。
程序的核心:AsyncTest()
这是该函数的一个简化版本,以便更容易阅读。
// Create the options object based on the UI checkboxes
RegexOptions regexOptions = new RegexOptions();
if (cbIgnoreCase.Checked) regexOptions |= RegexOptions.IgnoreCase;
if (cbCultureInvariant.Checked) regexOptions |= RegexOptions.CultureInvariant;
if (cbMultiLine.Checked) regexOptions |= RegexOptions.Multiline;
if (cbSingleLine.Checked) regexOptions |= RegexOptions.Singleline;
if (cbIndentedInput.Checked) regexOptions |= RegexOptions.IgnorePatternWhitespace;
// Creates the RegEx engine passing the RegEx string and the options object
Regex regex = new Regex(txtRegEx.Text, regexOptions);
// This executes the Regex and collects the results
// The execution isn't done until a member of the matchCollection is read.
// So I read the Count property for the regex to really execute from start to finish
MatchCollection matchCollection = regex.Matches(rtbText.Text);
int matchesFound = matchCollection.Count;
// Also do the RegEx replacement if the user asked for it
if (cbReplaceMode.Checked)
rtbResults.Text = regex.Replace(rtbText.Text, txtRepEx.Text);
// Add the Capture Group columns to the Results ListView
int[] groupNumbers = regex.GetGroupNumbers();
string[] groupNames = regex.GetGroupNames();
string groupName = null;
foreach (int groupNumber in groupNumbers)
{
if (groupNumber > 0)
{
groupName = "Group " + groupNumber;
if (groupNames[groupNumber] != groupNumber.ToString())
groupName += " (" + groupNames[groupNumber] + ")";
lvResult.Columns.Add(groupName, 100, HorizontalAlignment.Left);
}
}
// Process each of the Matches!
foreach (Match match in matchCollection)
{
//Add it to the grid
ListViewItem lvi = lvResult.Items.Add(match.ToString());
lvi.SubItems.Add(match.Index.ToString());
lvi.SubItems.Add(match.Length.ToString());
for (int c = 1; c < match.Groups.Count; c++)
{
lvi.SubItems.Add(match.Groups[c].Value);
}
//Highlight the match in the RichTextBox
rtbText.Select(match.Index, match.Length);
rtbText.SelectionColor = Color.Red;
}
异步执行功能。有趣的开始!
我最初使用 BackgroundWorker
来编码,但不得不放弃它,因为它似乎只在你想要中止你代码中的一个长时间循环时有用……但当你调用一个需要很长时间才能完成的外部函数时,它就无能为力了。
所以,我从头开始用更底层的 Thread
管理重新编码了它,结果发现一旦完成,它比以前的技术更简单、更清晰。
private Thread worker; // The worker that really does the execution in a separate thread.
private void MainForm_Load(object sender, System.EventArgs e)
{
// This is a critical line.
// It allows the other thread to access the controls of this class/object.
Control.CheckForIllegalCrossThreadCalls = false;
}
/// <summary>
/// Handle the multiple behaviors of the Test button based on its text
/// </summary>
private void btnTest_Click(object sender, System.EventArgs e)
{
if (btnTest.Text == STOPPED_MODE_BUTTON_TEXT)
{
StartTest();
}
else if (btnTest.Text == RUNNING_MODE_BUTTON_TEXT)
{
AbortTest();
}
}
/// <summary>
/// Prepare and launch the asynchronous execution using another thread
/// </summary>
private void StartTest()
{
// Creates the separate Thread for executing the Test
worker = new Thread(AsyncTest);
// After this instruction if the worker hangs and this thread exits,
// then nobody has to wait for the worker to finish.
// (e.g. The worker will be aborted if the user wants to close the app.)
worker.IsBackground = true;
// Start the Asynchronous Test function
worker.Start();
}
/// <summary>
/// Instructs to abort the asynchronous execution of the Test.
/// </summary>
private void AbortTest()
{
// This generates a ThreadAbortException at the worker function AsyncTest()
if (worker.IsAlive) worker.Abort();
}
/// <summary>
/// This is the core of the app. The RegEx execution and processing function.
/// It's being run on a separated thread.
/// </summary>
private void AsyncTest()
{
// Every line in this function is susceptible of a ThreadAbortException
// which is how the user is able to stop it.
try
{
sbpStatus.Text = "Test running...";
// ***************************************
// Here is the code that you already read
// in the previous section of this article
// [The core of the program: AsyncTest()]
// ***************************************
sbpStatus.Text = "Test success.";
}
catch (ThreadAbortException)
{
sbpStatus.Text = "Test aborted by the user.";
}
catch (Exception e)
{
sbpStatus.Text = "Test aborted by an error.";
// Any other Exception is shown to the user
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
// Restore the btnText functionality
btnTest.Text = STOPPED_MODE_BUTTON_TEXT;
}
}
程序历史
这个工具最初由 Davide Mauri(2003 年)编写。我在工作和个人项目中大量使用它。由于它是开源的,我开始添加我需要的新功能。有一天,程序已经大不相同,我想把所有这些改进都贡献给 Davide,所以我通过电子邮件联系了他,他允许我重新发布它,并给了我 Kurt Griffith 版本程序(2006 年)的链接。我将他的增强功能和我自己的功能进行了混合,并优化了用户界面。
推荐链接
- 正则表达式教程网站:https://regexper.cn/
- 正则表达式库:http://regexlib.com/
- 正则表达式备忘单:http://www.addedbytes.com/cheat-sheets/regular-expressions-cheat-sheet/
其他链接
- 作者邮箱:opablo aa-tt gmail dd-oo-tt com
- 作者公共 GitHub 仓库:https://github.com/opablo/RegExTester
- 作者 SF 项目(已弃用):http://sourceforge.net/projects/regextester
- Kurt Griffiths 的 CodeProject 文章:https://codeproject.org.cn/kb/string/dotnetregextest.aspx
- Davide Mauri 的 SF 项目:http://sourceforge.net/projects/regextest
- Davide Mauri 的主页:http://www.davidemauri.it/
文章历史
- 2011-05-21 - 文章已适配应用程序的新 3.2.0.0 版本
- 2009-05-03 - 文章已适配应用程序的新 3.1.0.0 版本
- 2008-03-08 - 将历史记录移到底部并更新了链接
- 2008-03-05 - 文章已适配应用程序的新 3.0.0.0 版本,增加了异步执行功能
- 2008-03-04 - 文章完全重写,以展示和注释项目中使用的代码片段
- 2008-03-02 - 初始文章
程序历史
- 2011-04-06 - 3.2.0.0 - 作者:Pablo Osés
- 新功能
- 检测捕获组内的多个捕获
- 次要更改
- 代码整理
- 关于窗口中的贡献者更新
- 新功能
- 2010-02-25 - 3.1.1.0 - 作者:Eric Lebetsamer
- 新功能
- 导出到 CSV
- 新功能
- 2009-05-03 - 3.1.0.0 - 作者:Pablo Osés
- 新功能
RegEx.Replace()
- 上下文菜单图标
- C# 代码片段复制
RichTextBox
的 WordWrap 功能- 执行时间
- Mono 兼容
- Bug 修复
- 标签拼写错误
- 新的
SuspendLayout
技术和大量代码重构
- 新功能
- 2008-03-05 - 3.0.0.0 - 作者:Pablo Osés
- 新功能
- 异步执行
- 复制功能增强
- 测试
Textbox
上下文菜单 - 查找功能
- 新功能
- 2008-03-03 - 2.0.1.0 - 作者:Pablo Osés
- 新功能
- 正则表达式备忘单
- Bug 修复
- 多行行为
- 性能问题
- 结果列表点击事件
- 新功能
- 2008-03-02 - 2.0.0.0 - 作者:Pablo Osés
- 新功能
- 捕获组名称
- 窗口最大化
- 热键
- 缩进输入
- 区域设置不变
- 可调整大小的面板
- 新功能
- 2006-xx-xx - 1.0.0.3 - 作者:Kurt Griffiths
- 新功能
- 复制和窗口大小调整
- 新功能
- 2003-xx-xx - 1.0.0.3 - 作者:Davide Mauri
- 原始版本