TP正则表达式原理和实例详解

TP正则表达式原理和实例详解(一)


为了对照的方便,目录设置跟TP帮助一样。



1.概述



“*?”这两个是最常用的通配符了,其实也是最简单的正则表达式,前者是任意个字符,后者是一个字符,在微软资源管理器中就可以用这两个符号,常用软件的搜索项中大多也支持。在Word中也是有类似的表达式的,如“^?”是任意字符、“^#”是任意数字、“^p”是回车等。TP的特色就是对汉字的支持,在2.2通配符中可以看到很多支持特定汉字的通配符。

除了对汉字的支持外,TP最大的特色是自定义替换和批量正则替换,也正由于这两大功能,使得处理词库可以做到千变万化,处理百万大词库的速度是一般专用软件所不能及的。



2.正则表达式的构成


一个正则表达式可以由几个分支构成,分支之间由“|”隔开,“|”必须是半角符号,如果对表达式的部分内容进行区分,就要用子表达式(见2.4子表达式),就是用括号括起来。分支只能查找项使用,不能在替换项中使用分支。



实例:


①你有一个词库,在每个词条的后面标有词条的字数,如:

×××× ××××× 5
×××× ×× 2
……

如果你要查找3字和4字的词条,你应在查找处输入:
3$|4$
“$”是行末,意思就是3结尾或者4结尾的词条。



②如果上面的例子中数字是用中文数字表示的,并且有的词条没标字数,如:

×××× ××××× 五
×××× ××× 三
×××× 十三
……



如果用“三$|四$”去查,肯定把“十三”的词条也查进去了,在“三、四”前面应该有空格,而“十三”的“三”前面是没空格的,我们就要用这个把他们区别开来。应把表达式写成:

\s(三$|四$)

“\s”是空白字符,这里是指空格,整句的意思就是:空格后面有“三”或“四”结尾的词条。前面有什么问题就不大了,当然写成“^.*\s(三$|四$)”意思还是一样的,“^.*”就是词条前任何内容。
省去括号就不行了,如改成“\s三$|四$”,一种情况是:空格“三”结尾的词条,另一种是单独“四”结尾的词条,这样十四、二十四等词条也包含在里面了。



2.1特殊符号



在词库整理中,“^、$、\t”比较常用,TAB字符在替换项中也可以使用,由于空格在批替换中不好使用,更加突出了“\t”的重要性,另外用TAB字符作为间隔符,便于在电子表格中进行处理。但是极点格式的词库是用空格来隔离编码和词条的,所以空格和TAB字符需要经常转换的。



在前面已经讲了“$”的运用例子,这里讲一个运用“^”的例子。如有一编码在前的极点格式词库,你要在每个编码前加上一个z,只要在

查找处输入:“^”,在替换处输入:“z”就可以了。



2.2通配符


在通配符中最常用的是“. \a \c \d \s”,分别代表任意字符、字母、汉字、数字、空白字符,这几个一定要牢记。范围要小,是汉字的要尽量用\c,是字母一定要用\a,是TAB字符就尽量用\t。



在批替换中空格只能用\s来表示,因为空格在批替换表中,被定义为查找和替换表达式的间隔符。
如:
aawt 工作

这样极点格式的词条,可以用这样的正则表达式来描述:
^\a+\s\c+$
其中+是任意多个至少一个的意思,整句的解释是:
行开始+多个字母+一个空白符(这里是一个空格)+多个汉字+行结束



2.3字符集


方括号里的字符串,只代表其中的一个,里面字符彼此之间是“或”的关系。


如有一个极点格式的拼音码表,你要其中以“vui”开头的特殊编码和词条删除,你只要
在查找处输入:
^[vui].*$
在替换处输入:
\d
进行替换即可
“^[vui].*$”的意思就是以vui之一的字母开头后面为任意内容的编码词条,“\d”的意思就是把查找的内容替换为空,同时把换行符也删除,如果没有\d就会留下一个空行。



既然是“或”的关系,字符集就可以用分支来表述,以下三个表达式的意义是一样的:
^[vui].*$
^(v|u|i).*$
^v.*$|^u.*$|^i.*$
好好理解这三条表达式,对掌握分支、子表达式和字符集有很大的助益。



如果你要在上例这个拼音码表中只留下以“vui”开头的特殊编码和词条,查找的内容要改为:
^[^vui].*$
在方括号内加个“^”就是“非”的意思,这个表达式就是指的是非vui开头的编码词条。




2.4子表达式



子表达式在前面已经讲到了,如:\s(三$|四$)、^(v|u|i).*$,也就是帮助中说的区分优先级的作用。在括号内用“|”分隔的内容,就是用来区分优先级的子表达式,实际原理跟字符集差不多的,结合正则表达式构成和字符集内容就好理解了。



另一个作用是引用,这是最精要的东西,很多批量正则替换表都要用到。
简单的理解就是,在前面用括号括起来的内容(子表达式),后面按顺序用“/”加数字表示引用前面匹配的内容。


我在解决坛友的问题中有一个查找叠词的例子,在这里分析几个词型:
学习学习(ABAB) 可以表示为:(\c\c)\1
(\c\c)就是任意代表双字词,\1就是代表前面的双字词。这里要注意不能把“(\c\c)”理解为“AA”的形式,(\c\c)不能匹配“呵呵”、“嘿嘿”,两个“\c”是不同的汉字,如要实现AA型的效果,就应该是:(\c)\1。
笑嘻嘻(ABB) 可以表示为:\c(\c)\1
一心一意(ABAC) 可以表示为:(\c)\c\1\c



以上的叠词是最

简单的引用,复杂的例子一定要注意“顺序”,如:
现在有“社会主义4现代化3建设2”这样类型的词条,也就是复合词里面标上单纯词的字数:
在查找处输入:
^(\f+)\~f(\f+)\~f?(\f*)\~f?(\f*)\~f?(\f*)\~f?(\f*)\~f?(\f*)\~f?(\f*)\~f?(\f*)$
在替换处输入:
\1\2\3\4\5\6\7\8\9
进行替换就把词条中数字全部去掉了,其他英文等单字节字符全部可以去除。


在查找表达式中,其中“\f+”就是一个以上双字节字符,当然包括汉字,“\~f”是一个非双字节字符。因为是复合词所以至少有两个单纯词构成,所以前面是“^(\f+)\~f(\f+)”,这样避免了查找替换单纯词条,后面是“~f?(\f*)”构成,就是可有可无。


整句查找表达式的意思就是查找2至9个单纯词加字数构成的复合词。
引用表达式必须按顺序与子表达式严格对应,“\1”必然是引用第一个括号里的内容,依次类推,“社会主义4现代化3建设2”中“\1”就是引用“社会主义”、“\2”引用“现代化”、“\3”引用“建设”,“\4”以后的内容未查找到匹配内容,引用为空,所以最后就会剩下“社会主义现代化建设”。


引用表达式数量应小于等于子表达式数量,在此例中替换处内容如改为:
\1\3
那么替换结果就是“社会主义建设”,就是只留下第一、三表达式的内容。


在TP中子表达式不能超过9个,此例中复合词一般不会超过9个单纯词,没什么问题,其他出现超过9个的情况怎么办呢,大家可以去参考一些我的一些优化、去优化等例子。



2.5重复指示符


关于复制指示符要注意两个方面的问题:


一是至少匹配一次与可以不匹配之间的区别
“\c\c\c?\c?”前面两个必须有,后面两个可以没有,所以是代表2-4个汉字,相当于\c{2,4}。
可有可无与至少一次的明确在于确定查找的范围,不要养成喜欢用“?、*”不确定重复指示符的习惯,该明确一定要明确,这样既能保证查找的准确性,另外在处理百万级词库和批替换表比较繁复时可以提高速度。在上一节处理复合词的例子中,查找表达式中开头用的就是“^(\f+)\~f(\f+)”,避免了对单纯词的查找,毕竟复合词是少数,如果加上“?、*”就会对单纯也进行空的替换,处理量要不知大上多少倍。


关于准确性,大家看了这个例子就明白了:
把二笔码表中带有的“,./;”标点编码的词条找出来,查找表达式应该是:
^\a\~f*\p\~f*\s.+$


首先“\a”就表示第一个肯定是字母,二笔只有声母才是首码


其次,后三码中有一个是“,./;”半角标点“\p”,就是我们要找的了,在它的前后都有可能有编码,所以要带“*”,而且也不能确定是字母还是标点,所以应该

是“\~f”单字节字符,连起来就是可有可无、可多可少的单字节字符“~f*”。
这里“\~f”后面一定要带“*”,“\p”后面一定不能带“?、*”,这就是准确性的要求。


最后,“\s.+”也应该是确定的,因为空白符肯定要有,编码以后词条也肯定要有。至于行首标志就不用说一定要有,且只能有一个,行末标志要看情况了,因为.+已经把后面一切都包括了,但一般还是要写上,这样完整些,不容易出错。



二是匹配次数尽可能多和尽可能少的区别


一般在词库处理中,由于很都很短,很少会用到匹配次数尽可能少的情况,但是重码多行长的时候就会用到,主要是用在文本类长行处理中。其实在TP在文本处理中运用很广,下面就是关于文本处理匹配次数的实例:
很多网络文章的双引号是英文双引号“"”
在查找处输入:
"(.{-})"
替换处输入:
“\1”
进行替换就可以转为全角引号。
如果在查找处输入的是:“"(.*)"”,这样每段只替换首尾,因为是最大范围的查找,中间所有的英文引号也包括进去了。


[ 本帖最后由 vu 于 2007-8-15 11:32 AM 编辑 ]
------------
替换表达式

替换表达式比较少,主要是对查找内容的引用、插入特殊字符、删除字符和格式的转换。在这里初学者一定要注意,替换表达式与查找表达式的区别,查找表达要区别种类繁多的字符,表达式要比替换表达式多得多。

查找表达式能在替换表达式中用的是子表达式,如:

在查找处输入:(\c\c)\c\1

在替换处输入:\1

那么查找到的是“学习再学习”的话,就会替换为“学习”,也就是说“\1”在查找处和替换处都是代表前面的“\c\c”。

极个别表达式在查找和替换是一样的,如:\t都是代表TAB字符,但是查找到的TAB字符不能在替换处用\t来表示引用,其实在替换处用\T或者其他表达式来表示TAB符都是可以的。

fficeffice" />



3.1 特殊字符

特殊字符主要分为三类:

一是引用类:可以用“\”加数字进行部分引用(就是子表达式),也可以用“\0”和“\&”进行完全引用。如把前面的例子改成:

在在查找处输入:(\c\c)\c\1

在替换处输入:\1-\&

则结果样式是:学习-学习再学习



二是插入类:\n(回车符)和\t(TAB符)比较常用。这两个相当于间隔符,分别用来区别行和行内字符块。

正则表达式是不能跨行处理的,那么要跨处理的时候怎么办呢?可以先去除回车符然后再恢复回车符,要注意分成一小段一小段地处理,如果整块文字只有一个回车,处理十万级以上的词库机器会吃不消的。在这方面有很多技巧待以后讲实例地时候再行讲解。

三是

删除类:\b(前删)和\d(后删),用得较多的是后删符,当然具体要根据实际情况而定。

如有这样的一段含有假回车的文字:

正则表达式是不能跨行处理的

,那么要跨处理的时候怎么办

呢?可以先去除回车符然后再

恢复回车符。



在查找处输入:\c$

在替换处输入:\d\&

这样可以把假回车删除,\c$意思行末汉字,\d\&就是把假回车删除然后再写上查找内容,这是向后删除的例子。

如果你要的就是这样块状的文字,可是有一个逗号在行首不好看,要把逗号、句号改在行末。可以这样:

在查找处输入:^(,|。)

在替换处输入:\b\&\n

^(,|。)意思就是标点形头的行,\b\&\n就是向前删除一个字符,把回车删除,然后重写查找的内容就是标点,再插入回车就完成了。

在实际运用中处理这种网络格式的文字比较复杂方法也很多,要看你源文字的格式和目标格式是什么而定,在这里只是说明一下删除表达式的运用。



3.2 替换函数

替换函数在原帮助中说得比较清楚了,对与字母格式的转换在码表中用得也很少,我在这里不详解了,在自定义替换表替换函数中再作详细说明。

总的来说,查找表达式做的是找到要处理的文字内容,替换表达式就是处理找到的内容,可以说是“米”跟“炊”的关系。 [ 本帖最后由 vu 于 2007-10-26 08:35 PM 编辑 ]
4. 自定义替换功能

自定义替换是TP的精髓之一,很多朋友对自定义替换理解不透,我想主要是要多看实例。关于自定义替换表如何操作我在前面的帖子里已讲了很多,不重复了,这里就讲讲原理和运用。

fficeffice" />

有这样的一个拼音码表:

中 zhong

国 guo

人 ren

……

对下面的词库进行自定义替换

中国

中国人

国人

……

结果是:

zhongguo

zhongguoren

guoren

……

为什么会是这样呢?其实很好理解,首先把“中”替换成“zhong”,然后再替换“国”,只是简单的批量字符替换而已,只是自动一条一条地处理,下面要讲的批量正则替换也是这个道理,只是它换成了表达式。如果里面有一条是“中国人民”那结果会是“zhongguoren民”,因为民字未进行替换,假定码表里没有民字。

全是编码(在这里是拼音)当然不是大家想要的,如果要实现这样的结果:

中zhong国guo

中zhong国guo人ren

国guo人ren

……

就得把自定义替换表改成:

中 中zhong

国 国guo

人 人ren

……

同样的道理就是把“中”替换成了“中zhong”。

对于编码来说这样的格式更实用:

中国 zhongguo

中国人 zgren

国人 guoren

……

这就有求于批

量正则替换了,单用自定义替换是没法做到的。

对于批量正则替换比较好理解,前面已经讲了道理跟自定义替换是一样的,就是多次查找替换任务集中在一起完成。

在WORD中查找替换太多了就用宏来处理,批量正则替换也是一样的,对于一些繁复的操作一条一条替换是不可想象的,在以前的帖子里很多替换表的内容我自己都记不住了,现在我们只要记一个一个的表就简单多了。

对于自定义替换表和批量正则替换表,查找内容和替换内容要用空格或Tab符隔开,也就是中间要有空白,查找内容和替换内容本身不能有空格。

要把这样的码表:

zhongguo中国2



zhongguoren中国人3



guoren国人2



……

变成:

中国 zhongguo

中国人 zhongguoren

国人 guoren

……



如下面的替换表是不合法的:

^(\~f ) (\ f+).* \2 \1

^$ \d

第一次替换意思是把行首“^”词“(\~f )”和编码“(\ f+)”对调位置,替换为编码在前“\2”在前词条“\1”在后,中间插入空格,并删除后面的多余内容。

第二条意思是删除去空行。

这里的问题就出在第一次替换,替换表达式中多了个空格,\2和\1之间不能有空格,可以在中间加个TAB符表达式,变成这样:

^(\~f ) (\ f+).* \2\t\1

^$ \d

等码表处理完毕了,可以在TP进行实际替换把TAB符替换为空格,其实TAB功能比空格强,这样转到电子表格很好处理,但是最终还是要变成空格的,所以最好能有专门的空格表达式,现版没有,建议下版能能增加空格表达式。

对于编码来说,自定义替换结合批量正则替换是最适合不过了,从这个帖子的标题中就可以看出其中的重要性了。但是现在还不能举这样的例子,因为要用到自定义替换表的替换函数,这是下一节的内容了。


[ 本帖最后由 vu 于 2007-10-26 09:03 PM 编辑 ]
4.1 在查找/替换中使用自定义替换表

上一节讲到把以下内容设自定义替换表1:

中 zhong

国 guo

人 ren

……

通过点击编辑>自定义替换>自定义替换表1,对以下内容进行处理:

中国

中国人

国人

……

结果是:

zhongguo

zhongguoren

guoren

……

这是自定义替换表的最原始用法,高级的用法是在查找/替换中使用自定义替换,最高级的用法是在批量替换表中使用。以上步骤在查找/替换中的用法是:

在查找处输入:(\c)

在替换处输入:\T{\1}

(\c)意思是把任一汉字设子表达式

\T{\1}意思是把子表达式1(查找到的汉字)由自定义替换表1进行替换,因为查找的是任意汉字,就对每个字进行替换了。

前面已经提到替换函数了,这里对自定义替换表替换

函数进行解释:

函数的表达式是:\Tn{…}

其中:\为表达式提示符,T表示自定义替换函数,n为自定义替换表的序号,大括号内的内容是函数的替换参数,也就是自定义替换表要处理的对象,可以是具体内容也可以是表达式。

前面例子中的\T{\1},因为是替换表1,可以把1省略了,当然写成\T1{\1}也是可以的。

用到两个以上替换表的情况也是有的,一种是处理复杂内容时必须用到多个自定义替换表,别一种是为了调试的方便,就多设几个替换表,省得改来改去。

对于自定义替换表比较大的,应及时地去除,否则下次启动时会占很大的资源,因为每次启动TP替换表的内容都是自动加载的。

替换参数相对难懂一点,大括号里的内容,就是我们要进行自定义替换的,如果大括号里面的内容是一个“中”字,那么\T{中}就是对“中”进行自定义替换,结果就是“zhong”,如果在上例中:

在查找处输入:(\c)

在替换处输入:\T{中}

结果是:

zhongzhong

zhongzhongzhong

zhongzhong

……

也就是把每个查找到的汉字都替换成了“zhong”。

如果替换处内容是:\T{\1},这样\1就是前面查到的汉字,如果查到的是“人”,就在自定义替换找到对应的是“ren”,这样每个字对应的是自己的匹配项。

对一些简单的处理,可以不用子表达式,也就是查找处不用括号,在替换处替换参数写作\0即可。上例可以这样执行替换:

在查找处输入:\c

在替换处输入:\T{\0}

还想简单的话,就省去替换参数,就剩下\T行了。

这是懒方法,在多个自定义替换表情况下就不行了,还有很多情况要使用子表达式替换的,如在上例中要达到这样的效果:

zhongguo 中国

zhongguoren 中国人

guoren 国人

……

可以这样完成:

在查找处输入:^(\c)(\c)(\c?)

在替换处输入:\T{\1}\T{\2}\T{\3}\t&

^(\c)(\c)(\c?)意思是二字词或者三字词,因为最后一个汉字是有问号的就是可有可无。

\T{\1}\T{\2}\T{\3}\t&意思是分别对查找到的汉字进行自定义替换,然后插入TAB符,最后重写一遍查到的内容,也就是查到的二、三字词。其中的\1、\2和\3分别对应查找中的三个括号,这在子表达式中已经学过的了。

现在这是全拼的编码,我们要把三字词,变成“首码+首码+全码”的格式,也就是要得到这样的结果:

zhongguo 中国

zgren 中国人

guoren 国人

……

这里就要引入一个过滤的概念,过滤就是对自定义替换表的内容进行筛选,现在我们要首码,在此例中就是拼音的第一字母,我们在此例中的自定义替换表1的内容是:

中 zhong

国 guo

人 ren


……

现在我们只要第一个字母就是z、g、r……,把拼音描述成:(\a)(\a*),就是一个字母加任意个字母,在设置自定义替换表中,把(\a)(\a*)写入过滤内容中,把以下内容设为批量替换表:

^(\c)(\c)$ \T{\1}\T{\2}\t&

^(\c)(\c)(\c) \T{\1}[1]\T{\2}[1]\T{\3}\t&

进行批替换后,就可以实现三字词的“首首全”格式的编码了。

第一条就是对二字进行全码编码。

第二条替换内容的[1]指的是自定义替换表中替换内容的第一个子表达式,在这里就是第一个字母。

用过滤的方式进行编码很简单,但我并不推荐用,一个是对初学者理解起来难,第二是操作起来麻烦,要手工填一下过滤表,很不方便。

反正通过批量替换都可以实现的,也就省去过滤这个步骤了。

基础知识介绍到这里结束了,要完全吃透,我认为还是要多写多试,一些正则表达式和替换规则就如同棋规,内容并不多,但是在具体运用中技巧就千变万化了。比如在五笔编码中,我写的多个批量替换表也是有差别的。在下一步我就全讲实例了。

[ 本帖最后由 vu 于 2007-10-26 08:57 PM 编辑 ]
-------
实例讲解(一)



首先讲的第一个是最常用的五笔格式编码的批替换表,过去对五笔格式编码的替换表介绍过,今天换一个全新的编法,自定义替换表还是要单字在前、编码在后的单字码表,批替换表如下:

^(.)(.?)(.?).*(.)$ \T{\1}1\T{\2}2\T{\3}3\T{\4}4\t&

(..).+123(..).+4\t(.*) \1\2\t\3

(.).+1(.).+23(..).+4\t(.*) \1\2\3\t\4

(.).+1(.).+2(.).+3(.).+4\t(.*) \1\2\3\4\t\5

详细解释:

^(.)(.?)(.?).*(.)$ \T{\1}1\T{\2}2\T{\3}3\T{\4}4\t&

#这个替换表的最大特点就是全部采用了任意通配符“.”,这样就可以用任意编码对任意字符进行编码了。

#查找部分分解:^为行首,(.)第一字符为确定字符,(.?)(.?)是第二三个字符可有可无,.*中间相隔任意个字符,(.)$最后结尾的一个确定字符。

#在这里第一个字符和最后一个字符是一定要有的,也就是说至少是二字词,第二字符出现的话,加上首末就是三字词了,第三字符出现的话就是四字词了,对这四个字符,分别设为了子表达式,其他的字符不参与编码,就略去了。

#替换部分分解:\T{\1}对第一个找到的字符进行自定义替换,1为插入标志数字,\T{\2}2\T{\3}3对三字词以上词条进行自定义替换,并插入标志数字,如果字符不存在就只插入数字,\T{\4}4对最后一个字符进行同样的处理,这一个编码一定存在,\t插入间隔符,&重写查找的内容,也就是词条。

#这样一行就完成了编码与词条的分离。

(..).+123(..).+4\t(.*) \1\2\t\3

#这一行对二字词进行编码,特征是查找内容中23前面是

空白,只有首末即14前面有编码。(..).+这就是编码,(..)此为前ffice:smarttags" />两码,就把它设子表达式,(.*)是词条内容。

#替换项中:\1\2是把二字的前两码写上,然后插入间隔符\t,最后写入词条\3。

(.).+1(.).+23(..).+4\t(.*) \1\2\3\t\4

#此行对三字词进行替换,特征是3前面没编码,前二字取第一码(.),第三码取前二码,就是(..).+4中的(..),替换项是依次写入编码和词条。

(.).+1(.).+2(.).+3(.).+4\t(.*) \1\2\3\4\t\5

#此行对四字以上词条进行编码,原理同上,只是各取第一码。

fficeffice" />

在理解的过程中,一定要对每一个表达式和代码的意思都要搞清楚,因为五笔编码个性化的编码方式很多,每个人要实现的目的也不同,大家理解了,就可以自己试着编些变化型。

[ 本帖最后由 vu 于 2007-10-26 09:10 PM 编辑 ]

相关文档
最新文档