最近做的项目又要用到正则表达式,但是因为很久没写了,手有点生,程序调试了好几次都没有达到预期匹配目标。就这样修改、编译、测试,来来回回重复了好几次,真是太麻烦了。
忽然想起来,以前在网上下载过一个正则表达式的测试工具,忘了叫什么名字,非常方便。可是我在硬盘里面又找不到了。于是决定自己动手写一个,应该也不是很难,预期目标是能够列出所有匹配项,并且对于每个匹配项列出所有的匹配组(Group)。
几经折腾,终于完工了,有测试工具还是爽多了,不必在IDE里反复的修改、编译了。而且,最大的好处就是,写Regular Expression不再是一件痛苦的事情了,没事的时候,就可以打开工具练练手。
贴张效果图:
图1. 提取出Baidu主页的所有链接及链接文字
今天还解决了一个困扰我很久的问题,就是关于正则表达式中“负向预查”的使用。定义:(?=pattern)是正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。而(?!pattern)是负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。负向预查有时会用在对[^]的扩充,[^]只是一些字符,而?!可以使整个字符串。
我就想当然的认为正则式:“aaa(?!bbb)ccc”应该可以匹配字符串“aaaQQQccc”,但是这种匹配却失败了。后来通过MSDN我了解到“负向预查”是不消耗字符的,也就是说QQQ匹配bbb失败以后,其实不是接着从“c”开始匹配,而是再从"Q"开始。
所以修改正则式为aaa(?!bbb)(.*?)ccc,测试!,匹配成功了。(注:问号表示非贪婪匹配。)
效果图:
附:正则表达式测试工具的源代码
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace WindowsApplication1
... {
public partial class Form1 : Form
...{
public Form1()
...{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
...{
string text = textBox1.Text;
string pattern = textBox2.Text;
Regex reg = null;
Match mc = null;
try
...{
RegexOptions regopts=new RegexOptions();
if(!checkBox1.Checked)regopts|=RegexOptions.IgnoreCase;
if (!checkBox2.Checked) regopts |= RegexOptions.Singleline;
else regopts |= RegexOptions.Multiline;
reg = new Regex(pattern, regopts);
mc = reg.Match(text);
}
catch (Exception ex)
...{
MessageBox.Show("错误的正则式:" + ex.Message);
return;
}
listView1.GridLines = true;
listView1.Clear();
listView1.Columns.Clear();
for (int i = 0; i < mc.Groups.Count; i++)
...{
listView1.Columns.Add("Group[" + i.ToString() + "]", 100);
}
while (mc.Success)
...{
ListViewItem item = new ListViewItem();
item.SubItems[0].Text = mc.Groups[0].Index.ToString() + ":" + mc.Groups[0].Value;
for (int i = 1; i < mc.Groups.Count; i++)
...{
item.SubItems.Add(mc.Groups[i] .Index.ToString()+ ":" + mc.Groups[i].Value);
}
listView1.Items.Add(item);
mc = mc.NextMatch();
}
listView1.Update();
}
}
}