最近做word脚注用到了正则表达式的匹配替换功能。我提取rtf字符串中书签的名称,更改名称后,再替换到字符串中。看代码:
1 var range = fd_Field.Result.Footnotes[1].Range; 18 str_Content = Regex.Replace(str_Content, @"\\bkmk(start|end) _(\w+)}", "\\bkmk$1 _$2_" + fid + "}", RegexOptions.Multiline); 19 20 PasteByClipboard(range, str_Content); 21 22 var maches=Regex.Matches(str_Content, @"\\bkmkstart _(\w+)}", RegexOptions.Multiline); 23 24 for (int i = 1; i <= range.Paragraphs.Count; i++) 25 { 26 if (maches.Count > 0) 27 { 28 if (maches[i - 1].Success) 29 { 30 31 if (maches[i - 1].Groups.Count > 0) 32 { 33 range.Paragraphs[i].ID = maches[i - 1].Groups[1].Value; 34 } 35 } 36 } 37 }
代码解释:str_Content中存储的是rtf格式的字符串,字符串中有word书签的定义,\v\bkmkstart _nf8f0c1a4cb18b4a8cae0338d4923c5cc1} 这是书签的开始位置,\v\bkmkend _nf8f0c1a4cb18b4a8cae0338d4923c5cc1}\par}, 这是书签的结束位置。\v表示书签的名称是隐藏的。第18行的黄色部分是正则表达式,绿色部分是要替换的内容,正则匹配书签开始和结束的名称,然后修改名称并替换。(\w+)匹配的是红色背景的部分。圆括号是正则表达式中的分组捕获。再看看替换的部分,\\bkmk$1 _$2_" + fid + "},$1引用第一个捕获分组,$2引用第二个捕获分组。fid是程序中的一个变量,表示域Id,这是一个string类型,它从域的Id变化而来。
从程序的第22行开始到结束,用正则 \\bkmkstart _(\w+)} 匹配修改后的书签名称,并把它作为rtf段落的Id值。这一段展示了程序如何读取分组捕获的值。Groups[0],存放的是整个正则匹配的结果,Groups[1],存放的是第一个分组匹配的结果。因此要取分组匹配的结果,从1开始。
正则的分组匹配替换功能的强大是毋庸置疑的,它使得程序变得简洁,但是仍然能满足我们各种需求。任何一种强大的技术好比一把锋利的剑,用好了事半功倍,用不好了,后患无穷。例如,我要用正则匹配连续的自然数。1,3,4,5,8 ,比如我要捕获3,4,5,用正则该怎么写呢?研究了半天,觉得无从下手,反而用程序实现起来简单的多。碰到字符串的处理,一些比较复杂的处理,首先想想正则能不能排上用场。学以致用,这是我学习技术的最大的快乐。