<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
	<channel>
		<title>释翔在线</title>
		<link>http://www.shixiang.info/</link>
		<description>人间五十年，万事如梦幻。一度生存者，岂有长不灭？</description>
		<copyright>Copyright (C) 2004 Security Angel Team [S4T] All Rights Reserved.</copyright>
		<generator>shanghuo Version 1.6 Build 20071004</generator>
		<lastBuildDate>Wed, 19 Nov 2008 14:10:58 +0000</lastBuildDate>
		<ttl></ttl>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=264</guid>
			<title>1周学会unix基本命令</title>
			<author>jiashixiang</author>
			<description><![CDATA[这篇东西是关于Unix系统操作的教程。也是Unix 的入门教程。如果你有兴趣学，请看下去，保证你可以学到许多有用的东西。如果你满足于dos,windows的操作，不想对网络服务器，有任何了解的话，可以不看。因为你并不想成为计算机高手。本教程仅仅讲授Unix 系统的常用命令，不涉及 Unix 的历史、安装和编程。如果你想得到更多的知识， 请查找其他的教材。本教程参考了《精通Unix》、《Unix基础》、《Unix系统使用指南 》等书，你可以在那里找到更多的知识。 <br /><br />准备知识： <br /><br />Unix是一个多任务多用户的操作系统。多任务是指可以同时运行几个不同的程序，或命令。在操作系统的术语里叫&ldquo;进程&rdquo;，就象在运行Windows95的时候我们可以一边听CD 一边打字，同时打印机还在工作。多用户是指一台运行Unix系统的机器可以同时具有几个不同的输入输出设备，给几个，几十个用户同时使用。不同的输入输出设备我们称为终端。 Unix 给每个终端设置不同的序号以协调工作，这个序号被称为终端序号。 Unix是一个根本不同于Dos的系统，无论其命令格式，用途都和Dos有很大区别。比如： 目录分割符是&quot;/&quot;,而不是&quot;\&quot;。具体的不同请参考其他书籍。 <br /><br />开始练习之前： <br /><br />在开始教授Unix命令之前，请先记下这个地址:<a href="http://www.cyberspace.org/" target="_blank"><font color="#22229c">http://www.cyberspace.org</font></a>。它是 一台在美国的，连上Internet的Unix主机。之所以告诉大家这个地址是因为它提供免费的帐号供大家使用。是免费的。就是说你可以先去那里申请一个帐号，然后在那里练习 你所学到的Unix命令。因为我相信不是每个朋友都可以轻松地得到Unix帐号的。 在你成功的申请好帐号之后，请在你Windows95的dos窗口里输入&quot;telnet cyberspace.org&quot; 等待连上主机。接下来就是输入你的用户名和密码，不要告诉我这些你都不会，如果你 不会的话，你是怎么连到这个网页的？ 现在假定你连上了主机，系统的提示符应该是&quot;cyberscpae.org%&quot;，对这个就是提示符 就象dos里&quot;c:\&gt;&quot;。接下去我将开始命令篇。 <br /><br />ls <br />你记不记得你学会的第一个Dos命令？反正我学会的第一个命令是dir：列目录和文件的命令。你学会的第一个Unix的命令也是列目录和文件的命令ls. 功能列出当前目录下的文件和目录。 同Dos一样，Unix系统命令也是带参数的。ls的参数有&quot;a&quot;,&quot;l&quot;,&quot;F&quot;。请注意，F是大写。 Unix系统里对命令的大小是严格区分的。（所以我们做网页常常会发生连接错误）同dos 不一样的地方在于，Unix命令的参数是&quot;-&quot;为其前导，而不是&quot;/&quot;。所以完整的ls命令是 <br />ls -l -a -F或ls -laF <br />-l:long的意思，把文件的其他资料，如文件长度，上次修改的日期等等列出来。 <br />-a:all的意思，把本目录下所有的文件，包括隐含的文件也列出来。 <br />-F:显示文件类型。&quot;*&quot;表示可执行文件，&quot;/&quot;表示目录，&quot;@&quot;表示连接。 <br />好，请在你的机器上输入ls -l -a -F，或许这是你一生里第一个Unix命令。记住了吗？ <br /><br />cd <br />变换目录，和Dos相同。如果你在cd后面没有给定目的地，则表示目的地是家目录。 在unix中有三中表示目录的符号&quot;.&quot;,&quot;..&quot;,&quot;~&quot;。 &quot;.&quot;表示当前目录路径的位置 &quot;..&quot;表示当前路径的上一层目录，或称&quot;父目录&quot; &quot;~&quot;表示家目录，所谓家目录指系统管理员分配给你的目录，比如你的用户名是li,那么 你的家目录就是在&quot;~li&quot;，在cd后面加上&quot;~li&quot;就是去你的家目录。 <br /><br />date <br />显示出当前的时间和日期，记住在Unix里你是无法修改系统时间的。输出时间一般是 格林威志时间。 <br /><br />who <br />该命令告诉你现在你使用的系统里有哪些用户。Unix是一个多用户的操作系统，同时在 机器上的可能有数十甚至数百人。who命令可以把他们的名字和终端号都列出来。who命令有 一个比较有趣的用法，&quot;who am I&quot;如其字面上的意思，让Unix显示你的用户名和终端类型 <br /><br />more <br />more命令有点象Dos里的Type命令，就是显示文本文件的内容。比如你要显示文件file1的 内容，可以用： more file1 当要看的文件超过屏幕可以容纳的行数，就会在屏幕的左下角出现一个&quot;--More--&quot;并告诉 你已经看过了整个文件的百分之几。如果要继续看下去，就敲&quot;Space Bar&quot;，可以看下一页， 或用&quot;Enter&quot;，就会读入下一行。 more命令还可以由你指定开始的行数。比如file1文件有1000行，你已经看过100行，那么可以用&quot;more +100 file1&quot;则直接从第100行开始看起。还有可以在命令里指定关键字。ore +/key_word 这样写，more就会从含有&quot;key_word&quot;字样的那一行的前两行开始显示。也许你已经注意到，Unix里对文本文件的操作要比Dos强大的多，实际上的确如此。 <br /><br />cp <br />cp命令同dos里的copy命令是一样的，复制文件。 比如： <br />cp file1 file2 <br />注意，如果你当前目录里已经含有file2这个文件，这个操作将会覆盖原来的file2。也许 在Dos里不会这样，它会要你确认。但你现在在用Unix，在你没有叫它确认之前，它不会那么做。 <br />cp -i file1 file2 <br />当你使用了-i这个选项，再遇到重名的情况系统将要你确认是否继续。 cp命令还有两个比较重要的选项:-r -p <br />cp -r /dir1 /dir_temp 这条命令是将目录dir1完全地复制到目录/dir_temp里，在Dos里着条命令叫xcopy <br />cp -p file1 file2 <br />Unix的系统和dos有一个不同的地方，在dos里copy一个文件是不会改变它的文件修改时间 的，除非你确实那样做了。在Unix里不同，它要改你的时间，或许它认为cp也是一种修改吧。 当你加上-p以后就不会改时间了。 <br />用惯Dos的人或许会对下面的一行命令大惑不解： <br />cp file1 file2 file3 dir_dest 这条命令把file1,file2,file3三个文件一起复制到/dir_dest里去。 <br /><br />***********思考问题，请说出以下命令的作用：******************** <br />cp file1+file2 file3 <br /><br />第二讲 <br />实际上以下命令的意义是这样的： <br />cp file1+file2 file3 <br />表示将一个名字为file1+file2的文件拷贝成file3。而不是在dos里的将file1和file2加在一起拷贝成文件file3。在unix的文件系统里，文件名字可以到255或254个字符，具体要看你到底使用那种类型的Unix。 <br /><br />cat <br />这个命令可不是&ldquo;猫&rdquo;的意思，而是catenate的缩写。顾名思义，是把东西串起来。比如： <br />cat file1 file2 <br />就是把文件file1和file2连在一起，然后输出到屏幕上。注意，输出到屏幕上是cat的自定义目的。如果要改变它的输出方向，就必须使用Unix系统的输出重定向符&ldquo;&gt;&rdquo; <br /><br />&gt; <br />输出重定向符。稍微高级一点的dos用户都知道这个符号。在Unix里的用法同Dos的区别不是很大。但比较不同的地方是，Unix系统将任何的一个外设都认同为一个文件。所以如果你要将输出重定向到打印机之类的地方，只要写上代表打印机的设备文件名。前一将里我们曾讲过终端机器名，它也是一个文件。比方我的设备机器是ttya，而小李的设备机器是ttyb，他想让我把当前目录的内容给他看。那么用这条命令就可以了 <br /><br />ls -a-u-F &gt;ttyb <br />这充分利用了Unix系统多用户的设计思想。同样的使用ls -a-u-F&gt;file1就是将当前目录列表输出到file1中。 <br /><br />又比如： <br />cat file1 file2&gt;file3 <br />就是将文件file1和file2的内容输出到file3中。在Dos里这条命令被写成 <br />copy file1+file2 file3 <br />当你用'&gt;'来输出重定向的时候，系统马上打开一个空文件来准备存放'&gt;'之前那个文件命令的输出结果。比如： <br />cat file1 file2&gt;file3 <br />系统先将file3的内容清空。所以： <br />cat file1 file2&gt;file1 <br />这条命令将产生一个错误提示。也许这条命令的本意是增加file1里的内容，但在系统初始这条命令的时候就把file1里的内容清空了。所以你得到一个错误提示。如果要追加文件内容请使用以下命令： <br />cat file2&gt;&gt;file1 <br />&quot;&gt;&gt;&quot;表示追加，而不是先清空file1中的内容。上面讲的是输出重定向，还有输入重定向。这个留在以后讲。 <br /><br />man <br />是英语&quot;manual&quot;的缩写。这是一条使用频率很高的命令，用来得到系统对一个特定命令的帮助信息。请各位读者一定要掌握这条命令。 <br />格式为：man -k 命令关键字 <br /><br />mv <br />这个命令是move的缩写，就是把一个目录或文件搬来搬去。实际上我常把它当成改文件名字的命令来用。比如：mv file1 ABC就是把文件file1改成ABC。 <br /><br />rm <br />记住rm是remove，是清除文件的意思。在Unix里是没有undelete这会事情的，所以请在使用的时候加上-i这个选项。表示确认。 <br /><br /><br />***********有许多朋友写信告诉我无法使用cyberspace的unix，也许是那里的速度比较慢。如果你实在没地方练习unix命令，我向你推荐一个工具，叫unixdos。它是一个unix环境的dos模拟器，基本上常用的unix命令你都可以使用。***************** <br /><br />第四讲 <br /><br />各位细心学习的朋友，非常感谢你能继续看这个教程。这个星期我们开始学习VI编辑器。从功能上说它是一个同EDIT基本一样的工具，但是它非常难学！以至于在现在我不得不引用一句在unix初学者口中的话来告戒大家&quot;To vi or not to vi,that is a question&quot;! <br />Vi的模式： <br />Vi有两种基本模式：命令模式和编辑模式，他们以<esc></esc>键切换。 <br />OK,我们启动一下vi,看看这么使用这个工具。 <br />%vi <br />启动vi,第一件事先按<esc></esc>，记得你在vi里要常常用它。然后输入&quot;i&quot;。 <br />屏幕上绝对不会出现任何字，因为<esc></esc>后你在命令模式，输入&quot;i&quot;则表示你进入编辑模式，并且现在的状态是insert，就是插入文本。 <br />如果你还没有被搞糊涂，那么继续输入。 <br />I love Unix. <br />是的，屏幕上出字了，你顺利地输入第一行文字。现在我们要保存这个文件。再按一次<esc></esc>，到命令模式，输入&quot;:w&quot;，表示存盘。你也可以输入 &quot;:w Unix.txt&quot;，那么就是以Unix.txt为文件名字存盘。 <br />好了基本vi概念就是如此。我把常用的一些命令都写在下面，你自己试着输入吧。 <br /><br />i &quot;insert&quot;的缩写 在光标之前插入文字 <br />a &quot;append&quot;的缩写 在光标之后插入文字 <br />o &quot;open&quot;的缩写 在光标所在行的下面开始新一行的输入 <br />O &quot;Open&quot;的缩写 在光标所在行的上面开始新一行的输入 <br /><br />第五讲 <br />本周的Unix教程是最后一讲了。在本讲里我们将讲一下unix Shell的基本内容。 我不准备深入地讲解Shell编程。因为要是那样的话，足够写上五十个page. <br />Shell是外层，是用户与Unix之间的层，它们节省命令行的长度，对命令参数执行完整的变换，并且定位和解释用户命令。另一方面，shell也是一个功能强大程序语言，提供制作工具的工厂。用Shell能创建用户自己的命令，甚至创建个完整的新环境。程序员里有一个流行称谓&ldquo;如果你不喜欢Unix界面，就自己写一个&rdquo;。实际上需深入到内核，便可以方便地控制自己的界面。可选的Shell有sh,csh,ksh有大的功能。 <br />正如其名字，Shell Script是一个文本文件。该文件指挥并控制Shell执行一系列特定的操作。一个批处理文件能含有任何命令（Unix的内部和外部命令），还可以包括过去编写的批处理文件。 <br />第一个Shell处理文件： <br />这里使用的Shell是BS，如果你是使用CS可以更改一部分内容。 <br />: <br />#@(#)dw--show data and users-- <br /># <br />date <br />who -u <br />第一个:不是必须的，而是长期的习惯。它告诉系统下面是BShell的内容。 <br />正如你看到的，Unix的Shell文件和Dos的批文件在很多地方是相同的。在写Unix的Shell文件时候，我们一般使用六个步骤： <br />1.计划好命令系列，并在键盘上试用 <br />2.为批处理文件挑一个好的，不会发生重复的文件名 <br />3.用你喜欢的编辑工具生成文件（希望不是VI:-)） <br />4.从冒号开始文件，以增加文件的解释 <br />5.用Chmod命令，将文件的属性设置为可读文件 <br />6.把批处理文件放入适合的目录中。 <br />以上是Unix系统的Shell文件一些基本的内容。这里就不多说了，实际上Shell文件同我们这些写网页的人关系并不大，但知道一些还是好的。]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=264</link>
			<category domain="http://www.shixiang.info/?cid=16">sever</category>
			<pubDate>2007-12-01 12:53</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=263</guid>
			<title>Linux下常用压缩格式的压缩与解压方法</title>
			<author>jiashixiang</author>
			<description><![CDATA[<p>.tar<br />解包： tar xvf FileName.tar<br />打包：tar cvf FileName.tar DirName<br />（注：tar是打包，不是压缩！）<br />---------------------------------------------<br />.gz<br />解压1：gunzip FileName.gz<br />解压2：gzip -d FileName.gz<br />压缩：gzip FileName<br />.tar.gz<br />解压：tar zxvf FileName.tar.gz<br />压缩：tar zcvf FileName.tar.gz DirName<br />---------------------------------------------<br />.bz2<br />解压1：bzip2 -d FileName.bz2<br />解压2：bunzip2 FileName.bz2<br />压缩： bzip2 -z FileName<br />.tar.bz2<br />解压：tar jxvf FileName.tar.bz2<br />压缩：tar jcvf FileName.tar.bz2 DirName<br />---------------------------------------------<br />.bz<br />解压1：bzip2 -d FileName.bz<br />解压2：bunzip2 FileName.bz<br />压缩：未知<br />.tar.bz<br />解压：tar jxvf FileName.tar.bz<br />压缩：未知<br />---------------------------------------------<br />.Z<br />解压：uncompress FileName.Z<br />压缩：compress FileName<br />.tar.Z<br />解压：tar Zxvf FileName.tar.Z<br />压缩：tar Zcvf FileName.tar.Z DirName<br />---------------------------------------------<br />.tgz<br />解压：tar zxvf FileName.tgz<br />压缩：未知<br />.tar.tgz<br />解压：tar zxvf FileName.tar.tgz<br />压缩：tar zcvf FileName.tar.tgz FileName<br />---------------------------------------------<br />.zip<br />解压：unzip FileName.zip<br />压缩：zip FileName.zip DirName<br />---------------------------------------------<br />.rar<br />解压：rar a FileName.rar<br />压缩：r ar e FileName.rar</p>
<p><br />rar请到：<a href="http://www.rarsoft.com/download.htm">http://www.rarsoft.com/download.htm</a> 下载！<br />解压后请将rar_static拷贝到/usr/bin目录（其他由$PATH环境变量指定的目录也可以）：<br />[root@www2 tmp]# cp rar_static /usr/bin/rar<br />---------------------------------------------<br />.lha<br />解压：lha -e FileName.lha<br />压缩：lha -a FileName.lha FileName</p>
<p>lha请到：<a href="http://www.infor.kanazawa-it.ac.jp/.../lhaunix/">http://www.infor.kanazawa-it.ac.jp/.../lhaunix/</a>下载！<br />&gt;解压后请将lha拷贝到/usr/bin目录（其他由$PATH环境变量指定的目录也可以）：<br />[root@www2 tmp]# cp lha /usr/bin/<br />---------------------------------------------<br />.rpm<br />解包：rpm2cpio FileName.rpm | cpio -div<br />---------------------------------------------<br />.tar .tgz .tar.gz .tar.Z .tar.bz .tar.bz2 .zip .cpio .rpm .deb .slp .arj .rar .ace .lha .lzh&nbsp;<br />.lzx .lzs .arc .sda .sfx .lnx .zoo .cab .kar .cpt .pit .sit .sea<br />解压：sEx x FileName.*<br />压缩：sEx a FileName.* FileName</p>
<p>sEx只是调用相关程序，本身并无压缩、解压功能，请注意！<br />sEx请到： <a href="http://sourceforge.net/projects/sex">http://sourceforge.net/projects/sex</a>下载！<br />解压后请将sEx拷贝到/usr/bin目录（其他由$PATH环境变量指定的目录也可以）：<br />[root@www2 tmp]# cp sEx /usr/bin/</p>
<p><br />参考文献：Linux 文件压缩工具指南<br />（其实看帮助是最好的方法，一般各个命令都可以用&ldquo;--help&rdquo;参数得到常用使用方法！）<br /></p>]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=263</link>
			<category domain="http://www.shixiang.info/?cid=16">sever</category>
			<pubDate>2007-11-29 10:04</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=262</guid>
			<title>职场杀手锏最冷的10个笑话</title>
			<author>jiashixiang</author>
			<description><![CDATA[<div class="t_msgfont" id="message160876">　　1、老师问一同学怎么减少白色污染？ <br /><br />&nbsp;&nbsp;　 同学答：把饭盒做成蓝色 <br /><br />&nbsp;&nbsp;　 2、飞机上,一位空中小姐问一个小女孩说:&ldquo;为什么飞机飞这么高都不会撞到星星呢？&rdquo; <br /><br />&nbsp; &nbsp;　小女孩回答到:&ldquo;我知道,因为星星会&lsquo;闪&rsquo;啊！&rdquo; <br /><br />&nbsp; &nbsp;　3、有一只北极熊和一只企鹅在一起耍,企鹅把身上的毛一根一根地拔了下来,拔完之后,对北极熊说:&ldquo;好冷哦！&ldquo;北极熊听了，也把自己身上的毛一根一根地拔了下来，转头对企鹅说：&ldquo;果然很冷！&rdquo; <br /><br />　　4、美国人∶你看过木头做的杯子吗？ <br /><br />&nbsp;&nbsp;　 中国人∶没有！ <br /><br />&nbsp; &nbsp;　美国人∶那为什麽你们中国字的&ldquo;杯&ldquo;是木字旁？ <br /><br />&nbsp; &nbsp;　中国人∶&ldquo;杯&ldquo;字旁边不是有个&ldquo;不&ldquo;字吗！也就是说它不是木头做的。<br /><br />　　5、某曰国战如火如荼，公会团长为了激励士气来到了大草原前线&hellip;&hellip; <br /><br />&nbsp;&nbsp;　 公会团长问：情况怎样？ <br /><br />&nbsp; &nbsp;　团员弓箭手报告说：报告团长！前方20公尺的帐棚旁有一个拜索斯的弓箭手，不过他的准度很烂，这几天射了好多次，都没有射到人。 <br /><br />&nbsp; &nbsp;　团长听完便问：既然发现敌国的弓箭手，为什么不把他干掉？ <br /><br />&nbsp; &nbsp;　团员弓箭手说：报告团长！不好吧，难道你要让他们换一个比较准的吗？ <br /><br />&nbsp; &nbsp;　6、众士兵：&ldquo;渴&hellip;&hellip;渴&hellip;&hellip;&rdquo; <br /><br />&nbsp;&nbsp;　 曹操：&ldquo;大家再坚持一会！我曾经到过这个地方，记得附近有一座梅林，再走一会可能就到了&ldquo;众士兵：&ldquo;噢&hellip;&hellip;有梅子吃呀&hellip;&hellip;噢&hellip;&hellip;&rdquo; <br /><br />&nbsp; &nbsp;　半个时辰后&mdash;&mdash;曹仁：&ldquo;主公！探险队找到了大量的水源！&rdquo; <br /><br />&nbsp;&nbsp;　 曹操：&ldquo;哈哈哈哈，大家听到了吗？终于有水喝啦&rdquo; <br /><br />&nbsp; &nbsp;　众士兵：&ldquo;不去&hellip;&hellip;一定要找到梅子&hellip;&hellip;&rdquo; <br /><br />&nbsp; &nbsp;　7、一块三分熟的牛排和一块5分熟的牛排在大街上遇到了，为什么他们没打招呼呢？ <br /><br />&nbsp; &nbsp;　因为&hellip;&hellip; <br /><br />&nbsp; &nbsp;　因为他们都不熟啊！哈哈 <br /><br />&nbsp; &nbsp;　8、小蛇很慌张地问大蛇哥哥：&ldquo;哥哥，我们有没有毒？&rdquo;大蛇说：&ldquo;你问这干吗？&rdquo; <br /><br />&nbsp; &nbsp;　小蛇说：&ldquo;我刚才不小心把自己舌头咬到了。&rdquo; <br /><br />　　9、龟兔赛跑，兔子很快跑到前面去了。 <br /><br />&nbsp; &nbsp;　乌龟看到一只蜗牛爬得很慢很慢，对他说：你上来，我背你吧。 <br /><br />&nbsp; &nbsp;　然后，蜗牛就上来了。 <br /><br />&nbsp;&nbsp;　 过了一会，乌龟又看到一只蚂蚁。对他说：你也上来吧。 <br /><br />&nbsp; &nbsp;　于是蚂蚁也上来了。 <br /><br />&nbsp; &nbsp;　蚂蚁上来以后，看到上面的蜗牛，对他说了句&ldquo;你好&rdquo; <br /><br />&nbsp; &nbsp;　你们知道蜗牛说什么吗? <br /><br />&nbsp; &nbsp;　蜗牛说:&ldquo;你抓紧点，这乌龟好快&rdquo; <br /><br />&nbsp; &nbsp;　10、坏消息：一个飞行员从飞机里掉出来了 <br /><br />&nbsp;&nbsp;　 好消息：他带了降落伞 <br /><br />&nbsp; &nbsp;　坏消息：降落伞是坏的 <br /><br />　&nbsp;&nbsp;好消息：下面有个干草堆 <br /><br />&nbsp; &nbsp;　坏消息：干草堆上有一杆大粪叉 <br /><br />&nbsp; &nbsp;　好消息：他没落到大粪叉上 <br /><br />&nbsp; &nbsp;　坏消息：他也没落到干草堆上</div>]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=262</link>
			<category domain="http://www.shixiang.info/?cid=13">火头军前锋</category>
			<pubDate>2007-11-19 13:27</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=261</guid>
			<title>一篇气死了99名老师的中学生作文！</title>
			<author>jiashixiang</author>
			<description><![CDATA[<div class="t_msgfont" id="message160883">　　今天是国庆节，放假一天，爸爸妈妈特地带我们到动物园玩。 <br /><br />　　按照惯例，我们早餐喜欢吃地瓜粥。今天因为地瓜卖完了，妈妈只好黔驴技穷地削些芋头来滥竽充数。没想到那些种在阳台的芋头很好吃，全家都贪得无厌地自食其果。 <br /><br />　　出门前，我那徐娘半老的妈妈打扮的花枝招展，鬼斧神工到一点也看不出是个糟糠之妻。头顶羽毛未丰的爸爸也赶紧洗心革面沐猴而冠，换上双管齐下的西装英俊得惨绝人寰，鸡飞狗跳到让人退避参舍。东施效颦爱漂亮的妹妹更是穿上调整型内衣愚公移山画虎类犬地打扮的艳光四射，趾高气昂地穿上新买的高跟鞋。 <br /><br />　　我们一丘之貉坐着素车白马，很快地到了动物园，不料参观的人多到豺狼当道草木皆兵，害我们一家骨肉分离。妻离子散的爸爸鞠躬尽瘁地到处广播，终于查找到差点认贼作父的我和遇人不淑的妹妹，困兽之斗中，我们螳臂当车力排众议推已及人到挤到猴笼前，鱼目混珠拍了张强颜欢笑的全家福。 <br /><br />　　接着到鸡鸣狗盗的鸟园欣赏风声鹤唳哀鸿遍野的大自然美妙音乐。后来爸爸口沫横飞地为我们指鹿为马时，吹来一阵凉风，让人毛骨悚然不寒而栗，妈妈连忙为爸爸黄袍加身，也叮嘱我们要节哀顺便。 <br /><br />　　到了傍晚，因为假日的关系，餐厅家家鹊占鸠巢六畜兴旺，所以妈妈带着我们孟母参迁，最后终于决定吃火锅。有家餐厅刚换壁纸，家徒四壁很是美丽，灯火阑珊配上四面楚歌，非常有气氛。十面埋伏的女服务生们四处招蜂引蝶，忙着为客人围魏救赵口蜜腹剑到让人误认到了西方极乐世界。 <br /><br />　　饥不择食的我们点了综合火锅，作怀不乱的爸爸当头棒喝先发制人，请求为虎作伥拿着刀子班门弄斧的女服务生，快点将狡兔死走狗烹，因为尸位素餐的我们一家子早就添油加醋完毕，就等着火锅赶快沈鱼落雁好问鼎中原，可惜锅盖太小，有点欲盖弥汤料沸腾后，热得乐不思蜀的我们赶紧解衣推食好大义灭亲上下其手，一网打尽捞个水落石出。 <br /><br />　　火锅在我们呼天呛地面红耳赤地蚕食鲸吞后，很快就只剩沧海一粟，和少数的漏网之鱼。母范犹存的妈妈想要丢参落四放冬粉时发现火苗已经危在旦夕，只好投鼠忌器。幸好狐假虎威的爸爸呼卢喝雉叫来店员抱薪救火，终于死灰复燃，也让如坐针毯的我们终饱私囊。鸟尽弓藏后，我们一家子酒囊饭袋，沆淡瀣一气，我和妹妹更是小人得志，沾沾自喜。 <br /><br />　　不料结帐的时候，老板露出庐山真面目，居然要一饭千金，爸爸气得吴牛喘月，妈妈也委曲地牛衣对泣。 <br /><br />　　啊！这三生有幸的国庆节，就在爸爸对着钱包自惭形秽大义灭亲后，我们全家江郎才尽，一败涂地。</div>]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=261</link>
			<category domain="http://www.shixiang.info/?cid=13">火头军前锋</category>
			<pubDate>2007-11-19 13:26</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=260</guid>
			<title>15条使人醒悟的生活中的定律</title>
			<author>jiashixiang</author>
			<description><![CDATA[<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/murphy_law_life_tips.html" target="_blank">墨菲定律</a></strong></font><br />我们在事前应该是尽可能想得周到、全面一些，如果真的发生不幸或者损失，就笑着应对吧，关键在于总结所犯的错误，而不是企图掩盖它。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/yang_qun_xiao_ying_life_tips.html" target="_blank">羊群效应</a></strong></font><br />对他人的信息不可全信也不可不信，凡事要有自己的判断，出奇能制胜，但跟随者也有后发优势，常法无定法！ </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/shui_tong_life_tips.html" target="_blank">水桶定律</a></strong></font><br />若个人的某些方面是自己短板，那就要尽快把它补起来。若自己是集体中的&ldquo;一块最短的木板&rdquo;，那就应该迎头赶上，不要拉集体的后腿。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/bu_zhi_de_law_life_tips.html" target="_blank">不值得定律</a></strong></font><br />要做有价值的事情，而且要富有激情与动力；若现实所迫，不能选择符合自己价值的事业，也不要消极对待或者直接放弃，应该学会改变自己，再努力向自己的奋斗目标前进。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/shou_biao_law_life_tips.html" target="_blank">手表定理</a></strong></font><br />坚定一个目标，建立一个标准，自己才能成功。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/80-20-rule-life-tips.html" target="_blank">80/20法则</a></strong></font><br />一些关键的小的投入和努力，通常可以产生大多数的结果、产出或酬劳。提高效率就要抓住那20％的重点。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/washington-force-law-life-tips.html" target="_blank">华盛顿合作规律</a></strong></font><br />团队一定要有合适的团队协助方式。而作为一名团队成员，我们要积极参与团队的沟通和协调，相互分工合作，共同取得成果。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/jiu-yu-wu-shui-law-life-tips.html" target="_blank">酒与污水定律</a></strong></font><br />&ldquo;一粒老鼠屎坏了一锅粥&rdquo;，对于坏的组员或东西，要在其开始破坏之前及时处理掉。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/jian-fa-zhe-xue-life-tips.html" target="_blank">减法哲学</a></strong></font><br />减出轻松，减出自在；减出健康，减出年轻；减出快乐，减出幸福！ </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/occam-razor-life-tips.html" target="_blank">奥卡姆剃刀定律</a></strong></font><br />万事万物应该<strong>尽量</strong>简单，而不是<strong>更</strong>简单。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/po-chuang-li-lun-life-tips.html" target="_blank">破窗理论</a></strong></font><br />从我做起，从身边做起。这不是空洞的口号，行动起来！ </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/bei-bo-ding-lv-life-tips.html" target="_blank">贝勃定律</a></strong></font><br />理性的分析事实，不要随意凭感觉论事 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/butterfly-effect-life-tips.html" target="_blank">蝴蝶效应</a></strong></font><br />防微杜渐，不能忽视小的漏洞和差错，以免造成大祸。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/matthew-effect-life-hacks.html" target="_blank">马太效应</a></strong></font><br />想在某一个领域保持优势，就必须在此领域迅速做大。再者，当目标领域有强大对手的情况下，就要另辟蹊径，找准对手的弱项和自己的优势。 </li>
<li><font color="#003300"><strong><a href="http://www.mifengtd.cn/articles/yun-lun-effect-life-hacks.html" target="_blank">晕轮效应</a></strong></font><br />在人际交往中，我们应该注意告诫自己不要被别人的晕轮效应所影响，而陷入晕轮效应的误区。</li>]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=260</link>
			<category domain="http://www.shixiang.info/?cid=18">成长</category>
			<pubDate>2007-11-09 14:17</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=258</guid>
			<title>正则表达式收藏（五）之微软的正则</title>
			<author>jiashixiang</author>
			<description><![CDATA[<div class="postText"><font size="2">正则表达式<br /><br />如果原来没有使用过正则表达式，那么可能对这个术语和概念会不太熟悉。不过，它们并不是您想象的那么新奇。<br /><br />请回想一下在硬盘上是如何查找文件的。您肯定会使用 ? 和 * 字符来帮助查找您正寻找的文件。? 字符匹配文件名中的单个字符，而 * 则匹配一个或多个字符。一个如 'data?.dat' 的模式可以找到下述文件：<br /><br />data1.dat<br /><br />data2.dat<br /><br />datax.dat<br /><br />dataN.dat<br /><br />如果使用 * 字符代替 ? 字符，则将扩大找到的文件数量。'data*.dat' 可以匹配下述所有文件名：<br /><br />data.dat<br /><br />data1.dat<br /><br />data2.dat<br /><br />data12.dat<br /><br />datax.dat<br /><br />dataXYZ.dat<br /><br />尽管这种搜索文件的方法肯定很有用，但也十分有限。? 和 * 通配符的有限能力可以使你对正则表达式能做什么有一个概念，不过正则表达式的功能更强大，也更灵活。<br /><br />正则表达式简介（微软）--3.使用正则表达式<br /><br />使用正则表达式<br /><br />在典型的搜索和替换操作中，必须提供要查找的确切文字。这种技术对于静态文本中的简单搜索和替换任务可能足够了，但是由于它缺乏灵活性，因此在搜索动态文本时就有困难了，甚至是不可能的。 <br /><br />使用正则表达式，就可以： <br /><br />1.测试字符串的某个模式。例如，可以对一个输入字符串进行测试，看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。 <br /><br />2.替换文本。可以在文档中使用一个正则表达式来标识特定文字，然后可以全部将其删除，或者替换为别的文字。 <br /><br />3.根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。<br /><br />例如，如果需要搜索整个 web 站点来删除某些过时的材料并替换某些HTML 格式化标记，则可以使用正则表达式对每个文件进行测试，看在该文件中是否存在所要查找的材料或 HTML 格式化标记。用这个方法，就可以将受影响的文件范围缩小到包含要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料，最后，可以再次使用正则表达式来查找并替换那些需要替换的标记。<br /><br />另一个说明正则表达式非常有用的示例是一种其字符串处理能力还不为人所知的语言。VBScript 是 Visual Basic 的一个子集，具有丰富的字符串处理功能。与 C 类似的 Visual Basic Scripting Edition 则没有这一能力。正则表达式给 Visual Basic Scripting Edition 的字符串处理能力带来了明显改善。不过，可能还是在 VBScript 中使用正则表达式的效率更高，它允许在单个表达式中执行多个字符串操作。<br /><br />正则表达式简介（微软）--4.正则表达式语法<br /><br />正则表达式语法<br /><br />一个正则表达式就是由普通字符（例如字符 a 到 z）以及特殊字符（称为元字符）组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板，将某个字符模式与所搜索的字符串进行匹配。<br /><br />这里有一些可能会遇到的正则表达式示例：<br /><br />Visual Basic VBScript 匹配 <br />Scripting Edition <br /><br />/^\[ \t]*$/ &quot;^\[ \t]*$&quot; 匹配一个空白行。 <br /><br />/\d{2}-\d{5}/ &quot;\d{2}-\d{5}&quot; 验证一个ID号码是否由一个2位字，一<br />个连字符以及一个5位数字组成。<br /><br />/&lt;(.*)&gt;.*&lt;\/\1&gt;/ &quot;&lt;(.*)&gt;.*&lt;\/\1&gt;&quot; 匹配一个 HTML 标记。 <br /><br /><br />下表是元字符及其在正则表达式上下文中的行为的一个完整列表：<br /><br />字符 描述 <br /><br />\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后<br />向引用、或一个八进制转义符。例如，'n' 匹配字符 &quot;n&quot;。'\n' <br />匹配一个换行符。序列 '\\' 匹配 &quot;\&quot; 而 &quot;\(&quot; 则匹配 &quot;(&quot;。 <br /><br />^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 <br />Multiline 属性，^ 也匹配 '\n' 或 '\r' 之后的位置。 <br /><br />$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的 <br />Multiline 属性，$ 也匹配 '\n' 或 '\r' 之前的位置。 <br /><br />* 匹配前面的子表达式零次或多次。例如，zo* 能匹配 &quot;z&quot; 以及<br />&quot;zoo&quot;。 * 等价于{0,}。 <br /><br />+ 匹配前面的子表达式一次或多次。例如，'zo+' 能匹配 &quot;zo&quot; 以<br />及 &quot;zoo&quot;，但不能匹配 &quot;z&quot;。+ 等价于 {1,}。 <br /><br />? 匹配前面的子表达式零次或一次。例如，&quot;do(es)?&quot; 可以匹配<br />&quot;do&quot; 或 &quot;does&quot; 中的&quot;do&quot; 。? 等价于 {0,1}。 <br /><br />{n} n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配<br />&quot;Bob&quot; 中的 'o'，但是能匹配 &quot;food&quot; 中的两个 o。 <br /><br />{n,} n 是一个非负整数。至少匹配n 次。例如，'o{2,}' 不能匹配 <br />&quot;Bob&quot; 中的 'o'，但能匹配 &quot;foooood&quot; 中的所有 o。'o{1,}' <br />等价于 'o+'。'o{0,}' 则等价于 'o*'。 <br /><br />{n,m} m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹<br />配 m 次。刘， &quot;o{1,3}&quot; 将匹配 &quot;fooooood&quot; 中的前三个o。<br />'o{0,1}'等价于'o?'。请注意在逗号和两个数之间不能有空格<br /><br />? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,},<br />{n,m}) 后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的 <br />匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜<br />索的字符串。例如，对于字符串 &quot;oooo&quot;，'o+?' 将匹配单个 <br />&quot;o&quot;，而 'o+' 将匹配所有 'o'。 <br /><br />. 匹配除 &quot;\n&quot; 之外的任何单个字符。要匹配包括 '\n' 在内的任<br />何字符，请使用象 '[.\n]' 的模式。 <br /><br />(pattern) 匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 <br />Matches 集合得到，在VBScript 中使用 SubMatches 集合，在<br />Visual Basic Scripting Edition 中则使用 $0&hellip;$9 属性。要<br />匹配圆括号字符，请使用 '\(' 或 '\)'。<br /><br />(?:pattern) 匹配 pattern 但不获取匹配结果，也就是说这是一个非获取匹<br />配，不进行存储供以后使用。这在使用 &quot;或&quot; 字符 (|) 来组合<br />一个模式的各个部分是很有用。例如， 'industr(?:y|ies) 就<br />是一个比 'industry|industries' 更简略的表达式。<br /><br />(?=pattern) 正向预查，在任何匹配 pattern 的字符串开始处匹配查找字符<br />串。这是一个非获取匹配，也就是说，该匹配不需要获取供以后<br />使用。例如，'Windows (?=95|98|NT|2000)' 能匹配&quot;Windows <br />2000&quot;中的&quot;Windows&quot;，但不能匹配&quot;Windows3 .1&quot;中&quot;Windows&quot;。<br />预查不消耗字符，也就是说，在一个匹配发生后，在最后一次匹<br />配之后立即开始下一次匹配的搜索，而不是从包含预查的字符之<br />后开始。 <br /><br />(?!pattern) 负向预查，在任何不匹配Negative lookahead matches the <br />search string at any point where a string not matching <br />pattern 的字符串开始处匹配查找字符串。这是一个非获取匹<br />配，也就是说，该匹配不需要获取供以后使用。例如'Windows<br />(?!95|98|NT|2000)' 能匹配 &quot;Windows 3.1&quot; 中的 &quot;Windows&quot;，<br />但不能匹配 &quot;Windows 2000&quot; 中的 &quot;Windows&quot;。预查不消耗字<br />符，也就是说，在一个匹配发生后，在最后一次匹配之后立即开<br />始下一次匹配的搜索，而不是从包含预查的字符之后开始 <br /><br />x|y 匹配 x 或 y。例如，'z|food' 能匹配 &quot;z&quot; 或 &quot;food&quot;。'(z|f)<br />ood' 则匹配 &quot;zood&quot; 或 &quot;food&quot;。 <br /><br />[xyz] 字符集合。匹配所包含的任意一个字符。例如， '[abc]' 可以<br />匹配 &quot;plain&quot; 中的 'a'。<br /><br />[^xyz] 负值字符集合。匹配未包含的任意字符。例如， '[^abc]' 可以<br />匹配 &quot;plain&quot; 中的'p'。 <br /><br />[a-z] 字符范围。匹配指定范围内的任意字符。例如，'[a-z]' 可以匹<br />配 'a' 到 'z' 范围内的任意小写字母字符。 <br /><br />[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如， <br />'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。<br /><br />\b 匹配一个单词边界，也就是指单词和空格间的位置。例如， <br />'er\b' 可以匹配&quot;never&quot; 中的 'er'，但不能匹配 &quot;verb&quot; 中<br />的 'er'。 <br /><br />\B 匹配非单词边界。'er\B' 能匹配 &quot;verb&quot; 中的 'er'，但不能匹<br />配 &quot;never&quot; 中的 'er'。<br /><br />\cx 匹配由x指明的控制字符。例如， \cM 匹配一个 Control-M 或<br />回车符。 x 的值必须为 A-Z 或 a-z 之一。否则，将 c 视为一<br />个原义的 'c' 字符。 <br /><br />\d 匹配一个数字字符。等价于 [0-9]。 <br /><br />\D 匹配一个非数字字符。等价于 [^0-9]。 <br /><br />\f 匹配一个换页符。等价于 \x0c 和 \cL。 <br /><br />\n 匹配一个换行符。等价于 \x0a 和 \cJ。 <br /><br />\r 匹配一个回车符。等价于 \x0d 和 \cM。 <br /><br />\s 匹配任何空白字符，包括空格、制表符、换页符等等。等价于 <br />[ \f\n\r\t\v]。 <br /><br />\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 <br /><br />\t 匹配一个制表符。等价于 \x09 和 \cI。 <br /><br />\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。 <br /><br />\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。 <br /><br />\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。<br /><br />\xn 匹配 n，其中 n 为十六进制转义值。十六进制转义值必须为确<br />定的两个数字长。例如， '\x41' 匹配 &quot;A&quot;。'\x041' 则等价<br />于 '\x04' &amp; &quot;1&quot;。正则表达式中可以使用 ASCII 编码。.<br /><br />\num 匹配 num，其中num是一个正整数。对所获取的匹配的引用。<br />例如，'(.)\1' 匹配两个连续的相同字符。 <br /><br />\n 标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n <br />个获取的子表达式，则 n 为后向引用。否则，如果 n 为八进制<br />数字 (0-7)，则 n 为一个八进制转义值。 <br /><br />\nm 标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有<br />is preceded by at least nm 个获取得子表达式，则 nm 为后<br />向引用。如果 \nm 之前至少有 n 个获取，则 n 为一个后跟文<br />字 m 的后向引用。如果前面的条件都不满足，若 n 和 m 均为<br />八进制数字 (0-7)，则 \nm 将匹配八进制转义值 nm。 <br /><br />\nml 如果 n 为八进制数字 (0-3)，且 m 和 l 均为八进制数字 (0-<br />7)，则匹配八进制转义值 nml。 <br /><br />\un 匹配 n，其中 n 是一个用四个十六进制数字表示的Unicode字<br />符。例如， \u00A9 匹配版权符号 (?)。 <br /><br />正则表达式简介（微软）--5.建立正则表达式<br /><br />建立正则表达式<br /><br />构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。 <br /><br />可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。对 Visual Basic Scripting Edition 而言，分隔符为一对正斜杠 (/) 字符。例如：<br /><br />/expression/<br /><br />对 VBScript 而言，则采用一对引号 (&quot;&quot;) 来确定正则表达式的边界。例如：<br /><br />&quot;expression&quot;<br /><br />在上面所示的两个示例中，正则表达式模式 (expression) 均存储在RegExp 对象的Pattern 属性中。<br /><br />正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。</font> <br /></div>]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=258</link>
			<category domain="http://www.shixiang.info/?cid=2">php学习</category>
			<pubDate>2007-10-31 15:04</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=257</guid>
			<title>正则表达式收藏（四）之MySQL的正则</title>
			<author>jiashixiang</author>
			<description><![CDATA[正则表达式（regex)是定义复杂查询的一个强有力的工具。 这里是一个简单的资料，它忽略了一些详细的信息。 <br />　　正则表达式定义了一个字符串的规则。最简单的正则表达式不包含任何保留字。例如，正则表达式hello只和字符串&ldquo;hello&rdquo;匹配。 <br /><br />　　一般的正则表达式使用了某些特殊的结构，所以它能匹配更多的字符串。例如，正则表达式hello|word既能匹配字符串&ldquo;hello&rdquo;也能匹配字符串&ldquo;word&rdquo;。 <br /><br />　　举一个更复杂一点的例子，正则表达式B[an]*s可以匹配字符串&ldquo;Bananas&rdquo;、&ldquo;Baaaaas&rdquo;、&ldquo;Bs&rdquo;以及其他任何以B开头以s结尾的字符串，中间可以包括任意个a和任意个n的组合。 <br /><br />　　一个正则表达式中的可以使用以下保留字 <br /><br />^ <br /><br />所匹配的字符串以后面的字符串开头 <br /><br />mysql&gt; select &quot;fonfo&quot; REGEXP &quot;^fo$&quot;; -&gt; 0（表示不匹配） <br /><br />mysql&gt; select &quot;fofo&quot; REGEXP &quot;^fo&quot;; -&gt; 1（表示匹配） <br /><br />$ <br /><br />所匹配的字符串以前面的字符串结尾 <br /><br />mysql&gt; select &quot;fono&quot; REGEXP &quot;^fono$&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;fono&quot; REGEXP &quot;^fo$&quot;; -&gt; 0（表示不匹配） <br /><br />. <br /><br />匹配任何字符（包括新行） <br /><br />mysql&gt; select &quot;fofo&quot; REGEXP &quot;^f.*&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;fonfo&quot; REGEXP &quot;^f.*&quot;; -&gt; 1（表示匹配） <br /><br />a* <br /><br />匹配任意多个a（包括空串) <br /><br />mysql&gt; select &quot;Ban&quot; REGEXP &quot;^Ba*n&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;Baaan&quot; REGEXP &quot;^Ba*n&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;Bn&quot; REGEXP &quot;^Ba*n&quot;; -&gt; 1（表示匹配） <br /><br />a+ <br /><br />匹配任意多个a（不包括空串) <br /><br />mysql&gt; select &quot;Ban&quot; REGEXP &quot;^Ba+n&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;Bn&quot; REGEXP &quot;^Ba+n&quot;; -&gt; 0（表示不匹配） <br /><br />a? <br /><br />匹配一个或零个a <br /><br />mysql&gt; select &quot;Bn&quot; REGEXP &quot;^Ba?n&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;Ban&quot; REGEXP &quot;^Ba?n&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;Baan&quot; REGEXP &quot;^Ba?n&quot;; -&gt; 0（表示不匹配）<br /><br />de|abc <br /><br />匹配de或abc <br /><br />mysql&gt; select &quot;pi&quot; REGEXP &quot;pi|apa&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;axe&quot; REGEXP &quot;pi|apa&quot;; -&gt; 0（表示不匹配） <br /><br />mysql&gt; select &quot;apa&quot; REGEXP &quot;pi|apa&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;apa&quot; REGEXP &quot;^(pi|apa)$&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;pi&quot; REGEXP &quot;^(pi|apa)$&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;pix&quot; REGEXP &quot;^(pi|apa)$&quot;; -&gt; 0（表示不匹配） <br /><br />(abc)* <br /><br />匹配任意多个abc（包括空串) <br /><br />mysql&gt; select &quot;pi&quot; REGEXP &quot;^(pi)*$&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;pip&quot; REGEXP &quot;^(pi)*$&quot;; -&gt; 0（表示不匹配） <br /><br />mysql&gt; select &quot;pipi&quot; REGEXP &quot;^(pi)*$&quot;; -&gt; 1（表示匹配） <br /><br />{1} <br /><br />{2,3} <br /><br />这是一个更全面的方法，它可以实现前面好几种保留字的功能 <br /><br />a* <br /><br />可以写成a{0,} <br /><br />a+ <br /><br />可以写成a{1,} <br /><br />a? <br /><br />可以写成a{0,1} <br /><br />　　在{}内只有一个整型参数i，表示字符只能出现i次；在{}内有一个整型参数i，后面跟一个&ldquo;，&rdquo;，表示字符可以出现i次或i次以上；在{}内只有一个整型参数i，后面跟一个&ldquo;，&rdquo;，再跟一个整型参数j,表示字符只能出现i次以上，j次以下（包括i次和j次）。其中的整型参数必须大于等于0，小于等于 RE_DUP_MAX（默认是255）。 如果有两个参数，第二个必须大于等于第一个 <br /><br />[a-dX] <br /><br />匹配&ldquo;a&rdquo;、&ldquo;b&rdquo;、&ldquo;c&rdquo;、&ldquo;d&rdquo;或&ldquo;X&rdquo; <br /><br />[^a-dX] <br /><br />匹配除&ldquo;a&rdquo;、&ldquo;b&rdquo;、&ldquo;c&rdquo;、&ldquo;d&rdquo;、&ldquo;X&rdquo;以外的任何字符。 <br /><br />&ldquo;[&rdquo;、&ldquo;]&rdquo;必须成对使用 <br /><br />mysql&gt; select &quot;aXbc&quot; REGEXP &quot;[a-dXYZ]&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;aXbc&quot; REGEXP &quot;^[a-dXYZ]$&quot;; -&gt; 0（表示不匹配） <br /><br />mysql&gt; select &quot;aXbc&quot; REGEXP &quot;^[a-dXYZ]+$&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;aXbc&quot; REGEXP &quot;^[^a-dXYZ]+$&quot;; -&gt; 0（表示不匹配） <br /><br />mysql&gt; select &quot;gheis&quot; REGEXP &quot;^[^a-dXYZ]+$&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;gheisa&quot; REGEXP &quot;^[^a-dXYZ]+$&quot;; -&gt; 0（表示不匹配） <br /><br />[[.characters.]] 表示比较元素的顺序。在括号内的字符顺序是唯一的。但是括号中可以包含通配符,所以他能匹配更多的字符。举例来说：正则表达式[[.ch.]]*c匹配chchcc的前五个字符。 <br /><br />[=character_class=] <br /><br />表示相等的类，可以代替类中其他相等的元素，包括它自己。例如，如果o和(+)是一个相等的类的成员，那么[[=o=]]、[[=(+)=]]和[o(+)]是完全等价的。 <br /><br />[:character_class:] <br /><br />在括号里面，在[:和:]中间是字符类的名字，可以代表属于这个类的所有字符。字符类的名字有: alnum、digit、punct、alpha、graph、space、blank、lower、upper、cntrl、print和xdigit <br /><br />mysql&gt; select &quot;justalnums&quot; REGEXP &quot;[[:alnum:]]+&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;!!&quot; REGEXP &quot;[[:alnum:]]+&quot;; -&gt; 0（表示不匹配） <br /><br />[[:&lt;:]] <br /><br />[[:&gt;:]] <br /><br />分别匹配一个单词开头和结尾的空的字符串，这个单词开头和结尾都不是包含在alnum中的字符也不能是下划线。 <br /><br />mysql&gt; select &quot;a word a&quot; REGEXP &quot;[[:&lt;:]]word[[:&gt;:]]&quot;; -&gt; 1（表示匹配） <br /><br />mysql&gt; select &quot;a xword a&quot; REGEXP &quot;[[:&lt;:]]word[[:&gt;:]]&quot;; -&gt; 0（表示不匹配） <br /><br />mysql&gt; select &quot;weeknights&quot; REGEXP &quot;^(wee|week)(knights|nights)$&quot;; -&gt; 1（表示匹配）<br />]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=257</link>
			<category domain="http://www.shixiang.info/?cid=2">php学习</category>
			<pubDate>2007-10-31 14:59</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=256</guid>
			<title>正则表达式收藏（三）之高级技巧</title>
			<author>jiashixiang</author>
			<description><![CDATA[什么是RE?<br />　　想必各位大大在做文件查找的时侯都有使用过万用字符&rdquo;*&rdquo;，比如说想查找在Windows目录下所有的Word文件时，你可能就会用&rdquo;*.doc&rdquo;这样的方式来做查找，因为&rdquo;*&rdquo;所代表的是任意的字符。RE所做的就是类似这样的功能，但其功能更为强大。<br /><br />　　写程序时，常需要比对字符串是否符合特定样式，RE最主要的功能就是来描述这特定的样式，因此可以将RE视为特定样式的描述式，举个例子来说，&rdquo;\w+&rdquo;所代表的就是任何字母与数字所组成的非空字符串(non-null string)。在.NET framework中提供了非常强大的类别库，藉此可以很轻易的使用RE来做文字的查找与取代、对复杂标头的译码及验证文字等工作。<br />接下来，就让我们来体验一些例子吧。<br /><br />　　一些简单的例子<br />　　假设要查找文章中Elvis后接有alive的文字符串的话，使用RE可能会经过下列的过程，括号是所下RE的意思：<br /><br />　　1. elvis (查找elvis)<br /><br />　　上述代表所要查找的字符顺序为elvis。在.NET中可以设定乎略字符的大小写，所以&rdquo;Elvis&rdquo;、&rdquo;ELVIS&rdquo;或者是&rdquo;eLvIs&rdquo;都是符合1所下的RE。但因为这只管字符出现的顺序为elvis，所以pelvis也是符合1所下的RE。可以用2的RE来改进。<br /><br />　　2. \belvis\b (将elvis视为一整体的字查找，如elvis、Elvis乎略字符大小写时)<br />&ldquo;\b&rdquo;在RE中有特别的意思，在上述的例子中所指的就是字的边界，所以\belvis\b用\b把elvis的前后边界界定出来，也就是要elvis这个字。<br /><br />　　假设要将同一行里elvis后接有alive的文字符串找出来，此时就会用到另外二个特别意义的字符&rdquo;.&rdquo;及&rdquo;*&rdquo;。&rdquo;.&rdquo;所代表就是除了换行字符的任意字符，而&rdquo;*&rdquo;所代表的是重复*之前项目直到找到符合RE的字符串。所以&rdquo;.*&rdquo;所指的就是除了换行字符外的任意数目的字符数。所以查找同一行里elvis后接有alive的文字符串找出来，则可下如3之RE。<br /><br />　　3. \belvis\b.*\balive\b (查找elvis后面接有alive的文字符串，如elvis is alive)<br /><br />　　用简单之特别字符就可以组成功能强大的RE，但也发现当使用越来越多的特别字符时，RE就会越来越难看得懂了。<br /><br /><br />再看看另外的例子<br />　　组成有效的电话号码<br /><br />　　假使要从网页上收集顾客格式为xxx-xxxx的7位数字的电话号码，其中x是数字，RE可能会这样写。<br /><br />　　4. \b\d\d\d-\d\d\d\d (查找七位数字之电话号码，如123-1234)<br />　　每一个\d代表一个数字。&rdquo;-&rdquo;则是一般的连字符号，为避免太多重复的\d，RE可以改写成如5的方式。<br /><br />　　5. \b\d{3}-\d{4} (查找七位数字电话号码较好的方法，如123-1234)<br />　　在\d后的{3}，代表重复前一个项目三次，也就是相等于\d\d\d。<br /><br />　　RE的学习及测试工具 Expresso<br /><br />　　因为RE不易阅读及使用者容易会下错RE的特性，Jim大大开发了一个工具软件Expresso，用来帮助使用者学习及测试RE，除了上面所述的网址之外，也可以上Ultrapico网站。安装完expresso后，在expression%20%20library中，jim大大把文章的例子都建立在其中，可以边看文章边测试，也可以试着修改范例所下的re，马上可以看到结果，小弟觉得非常好用。各位大大可以试试。/&quot;。安装完Expresso后，在Expression Library中，Jim大大把文章的例子都建立在其中，可以边看文章边测试，也可以试着修改范例所下的RE，马上可以看到结果，小弟觉得非常好用。各位大大可以试试。 <br /><br />　　.NET中RE的基础概念<br />　　特殊字符<br /><br />　　有些字符有特别的意义，比如之前所看到的&rdquo;\b&rdquo;、&rdquo;.&rdquo;、&rdquo;*&rdquo;、&rdquo;\d&rdquo;等。&rdquo;\s&rdquo;所代表的是任意空格符，比如说spaces、tabs、newlines等.。&rdquo;\w&rdquo;代表是任意字母或数字字符。<br /><br />　　再看一些例子吧<br />　　6. \ba\w*\b (查找a开头的字，如able)<br />　　这RE描述要查找一个字的开始边界(\b)，再来是字母&rdquo;a&rdquo;，再加任意数目的字母数字(\w*)，再接结束这个字的结束边界(\b)。<br /><br />　　7. \d+ (查找数字字符串)<br />　　&ldquo;+&rdquo;和&rdquo;*&rdquo;非常相似，除了+至少要重复前面的项目一次。也就是说至少有一个数字。<br /><br />　　8. \b\w{6}\b (查找六个字母数字的字，如ab123c)<br /><br />　　下表为RE常用的特殊字符<br /><br />　　. 除了换行字符的任意字符<br />　　\w 任意字母数字字符<br />　　\s 任意空格符<br />　　\d 任意数字字符<br />　　\b 界定字的边界<br />　　^ 文章的开头，如&rdquo;^The'' 用以表示出现于文章开头的字符串为&rdquo;The&rdquo;<br />　　$ 文章的结尾，如&rdquo;End$&rdquo;用以表示出现在文章的结尾为&rdquo;End&rdquo;<br />　　特殊字符&rdquo;^&rdquo;及&rdquo;$&rdquo;是用来查找某些字必需是文章的开头或结尾，这在验证输入是否符合某一样式时特别用有，比如说要验证七位数字的电话号码，可能会输入如下9的RE。<br /><br />　　9. ^\d{3}-\d{4}$ (验证七位数字之电话号码)<br /><br />　　这和第5个RE相同，但其前后都无其它的字符，也就是整串字符串只有这七个数字的电话号码。在.NET中如果设定Multiline这个选项，则&rdquo;^&rdquo;和&rdquo;$&rdquo;会每行进行比较，只要某行的开头结尾符合RE即可，而不是整个文章字符串做一次比较。<br /><br />　　转意字符(Escaped characters)<br /><br />　　有时可能会需要&rdquo;^&rdquo;、&rdquo;$&rdquo;单纯的字面意义(literal meaning)而不要将它们当成特殊字符，此时&rdquo;\&rdquo;字符就是用来移除特殊字符特别意义的字符，因此&rdquo;\^&rdquo;、&rdquo;\.&rdquo;、&rdquo;\\&rdquo;所代表的就是&rdquo;^&rdquo;、&rdquo;.&rdquo;、&rdquo;\&rdquo;的字面意义。<br /><br />　　重复前述项目<br /><br />　　在前面看过&rdquo;{3}&rdquo;及&rdquo;*&rdquo;可以用来重复前述字符，之后我们会看到如何用同样的语法重复整个次描述(subexpressions)。下表是使用重复前述项目的一些方式。<br /><br />　　* 重复任意次数<br />　　+ 重复至少一次<br />　　? 重复零次或一次<br />　　{n} 重复n次<br />　　{n,m} 重复至少n次，但不超过m次<br />　　{n,} 重复至少n次<br /><br />　　再来试一些例子吧<br /><br />　　10. \b\w{5,6}\b (查找五个或六个字母数字字符的字，如as25d、d58sdf等)<br />　　11. \b\d{3}\s\d{3}-\d{4} (查找十个数字的电话号码，如800 123-1234)<br />　　12. \d{3}-\d{2}-\d{4} (查找社会保险号码，如 123-45-6789)<br />　　13. ^\w* (每行或整篇文章的第一个字)<br />　　在Espresso可试试有Multiline和没Multiline的不同。<br /><br />　　匹配某范围的字符<br /><br />　　有时需要查找某些特定的字符时怎么辨?这时中括号&rdquo;[]&rdquo;就派上了用场。因此[aeiou]所要查找的是&rdquo;a&rdquo;、&rdquo;e&rdquo;、&rdquo;i&rdquo;、&rdquo;o&rdquo;、&rdquo;u&rdquo;这些元音，[.?!]所要查找的是&rdquo;.&rdquo;、&rdquo;?&rdquo;、&rdquo;!&rdquo;这些符号，在中括号中的特殊字符的特别意义都会被移除，也就是解译成单纯的字面意义。也可以指定某些范围的字符，如&rdquo;[a-z0-9]&rdquo;，所指的就是任意小写字母或任意数字。<br /><br />　　接下来再看一个比较初复杂查找电话号码的RE例子<br /><br />　　14. \(?\d{3}[( ] \s?\d{3}[- ]\d{4} (查找十位数字之电话号码，如(080) 333-1234 )<br /><br />　　这样的RE可查找出较多种格式的电话号码，如(080) 123-4567、511 254 6654等。&rdquo;\(?&rdquo;代表一个或零个左小括号&rdquo;(&ldquo;，而&rdquo;[( ]&rdquo;代表查找一个右小括号&rdquo;)&rdquo;或空格符，&rdquo;\s?&rdquo;指一个或零个空格符组。但这样的RE会将类似&rdquo;800) 45-3321&rdquo;这样的电话找出来，也就是括号没有对称平衡的问题，之后会学到择一(alternatives)来决解这样的问题。<br /><br />　　不包含在某特定字符组里(Negation)<br /><br />　　有时需要查找在包含在某特定字符组里的字符，下表说明如何做类似这样的描述。<br /><br />　　\W 不是字母数字的任意字符<br />　　\S 不是空格符的任意字符<br />　　\D 不是数字字符的任意字符<br />　　\B 不在字边界的位置<br />　　[^x] 不是x的任意字符<br />　　[^aeiou] 不是a、e、i、o、u的任意字符<br /><br />　　15. \S+ (不包含空格符的字符串)<br /><br />　　择一(Alternatives)<br /><br />　　有时会需要查找几个特定的选择，此时&rdquo;|&rdquo;这个特殊字符就派上用场了，举例来说，要查找五个数字及九个数字(有&rdquo;-&rdquo;号)的邮政编码。<br /><br />　　16. \b\d{5}-\d{4}\b|\b\d{5}\b (查找五个数字及九个数字(有&rdquo;-&rdquo;号)的邮政编码)<br /><br />　　在使用Alternatives时需要注意的是前后的次序，因为RE在Alternatives中会优先选择符合最左边的项目，16中，如果把查找五个数字的项目放在前面，则这RE只会找到五个数字的邮政编码。了解了择一，可将14做更好的修正。<br /><br />　　17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} (十个数字的电话号码)<br /><br />　　群组(Grouping)<br /><br />　　括号可以用来介定一个次描述，经由次描述的介定，可以针对次描述做重复或及他的处理。<br /><br />　　18. (\d{1,3}\.){3}\d{1,3} (寻找网络地址的简单RE)<br /><br />　　此RE的意思第一个部分(\d{1,3}\.){3}，所指的是，数字最小一位最多三位，并且后面接有&rdquo;.&rdquo;符号，此类型的共有三个，之后再接一到三位的数字，也就是如192.72.28.1这样的数字。<br /><br />　　但这样会有个缺点，因为网络地址数字最多只到255，但上述的RE只要是一到三位的数字都是符合的，所以这需要让比较的数字小于256才行，但只单独使用RE并无法做这样的比较。在19中使用择一来将地址的限制在所需要的范围内，也就是0到255。<br /><br />　　19. ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) (寻找网络地址)<br /><br />　　有没有发觉RE越来越像外星人说的话了?就以简单的寻找网络地址，直接看RE都满难理解的哩。<br /><br />　　Expresso Analyzer View<br /><br />　　Expresso提供了一个功能，它可以将所下的RE变成树状的说明，一组组的分开说明，提供了一个好的除错环境。其它的功能，如部分符合(Partial Match只查找反白RE的部分)及除外符合(Exclude Match只不查找反白RE的部分)就留给各位大大试试啰。<br /><br />　　当次描述用括号群组起来时，符合次描述的文字可用在之后的程序处理或RE本身。在预设的情型下，所符合的群组是由数字命名，由1开始，由顺序是由左至右，这自动群组命名，可在Expresso中的skeleton view或result view中看到。<br /><br />　　Backreference是用来查找群组中抓取的符合文字所相同的文字。举例来说&rdquo;\1&rdquo;所指符合群组1所抓取的文字。<br /><br />　　20. \b(\w+)\b\s*\1\b (寻找重复字，此处说的重复是指同样的字，中间有空白隔开如dog dog这样的字)<br />(\w+)会抓取至少一个字符的字母或数字的字，并将它命名为群组1，之后是查找任意空格符，再接和群组1相同的文字。<br /><br />　　如果不喜欢群组自动命名的1，也可以自行命名，以上述例子为例，(\w+)改写为(?&lt;Word&gt;\w+)，这就是将所抓取的群组命名为Word，Backreference就要改写成为\k&lt;Word&gt;<br />21. \b(?&lt;Word&gt;\w+)\b\s*\k&lt;Word&gt;\b (使用自行命名群组抓取重复字)<br /><br />　　使用括号还有许多特别的语法元素，比较通用的列表如下：<br /><br />　　抓取(Captures) <br />　　(exp) 符合exp并抓取它进自动命名的群组<br />　　(?&lt;name&gt;exp) 符合exp并抓取它进命名的群组name<br />　　(?:exp) 符合exp，不抓取它<br />　　Lookarounds <br />　　(?=exp) 符合字尾为exp的文字<br />　　(?&lt;=exp) 符合前缀为exp的文字<br />　　(?!exp) 符合后面没接exp字尾的文字<br />　　(?&lt;!exp) 符合前面没接exp前缀的文字<br />　　批注Comment <br />　　(?#comment) 批注<br /><br />　　Positive Lookaround<br /><br />　　接下来要谈的是lookahead及lookbehind assertions。它们所查找的是目前符合之前或之后的文字，并不包含目前符合本身。这些就如同&rdquo;^&rdquo;及&rdquo;\b&rdquo;特殊字符，本身并不会对应任何文字(用来界定位置)，也因此称做是zero-width assertions，看些例子也许会清楚些。<br /><br />　　(?=exp)是一个&rdquo;zero-width positive lookahead assertion&rdquo;。它指的就是符合字尾为exp的文字，但不包含exp本身。<br /><br />　　22. \b\w+(?=ing\b) (字尾为ing的字，比如说filling所符合的就是fill)<br />(?&lt;=exp)是一个&rdquo;zero-width positive lookbehind assertion&rdquo;。它指的就是符合前缀为exp的文字，但不包含exp本身。<br /><br />　　23. (?&lt;=\bre)\w+\b (前缀为re的字，比如说repeated所符合的就是peated)<br />　　24. (?&lt;=\d)\d{3}\b (在字尾的三位数字，且之前接一位数字)<br />　　25. (?&lt;=\s)\w+(?=\s) (由空格符分隔开的字母数字字符串)<br /><br />　　Negative Lookaround<br /><br />　　之前有提到，如何查找一个非特定或非在特定群组的字符。但如果只是要验证某字符不存在而不要对应这些字符进来呢?举个例子来说，假设要查找一个字，它的字母里有q但接下来的字母不是u，可以用下列的RE来做。<br /><br />　　26. \b\w*q[^u]\w*\b (一个字，其字母里有q但接下来的字母不是u)<br /><br />　　这样的RE会有一个问题，因为[^u]要对应一个字符，所以若q是字的最后一个字母，[^u]这样的下法就会将空格符对应下去，结果就有可能会符合二个字，比如说&rdquo;Iraq haha&rdquo;这样的文字。使用Negative Lookaround就能解决这样的问题。<br /><br />　　27. \b\w*q(?!u)\w*\b (一个字，其字母里有q但接下来的字母不是u)<br />　　这是&rdquo;zero-width negative lookahead assertion&rdquo;。<br /><br />　　28. \d{3}(?!\d) (三个位的数字，其后不接一个位数字)<br /><br />　　同样的，可以使用(?&lt;!exp)，&rdquo;zero-width negative lookbehind assertion&rdquo;，来符合前面没接exp前缀的文字符串。<br /><br />　　29. (?&lt;![a-z ])\w{7} (七个字母数字的字符串，其前面没接字母或空格)<br /><br />30. (?&lt;=&lt;(\w+)&gt;.*(?=&lt;\/\1&gt; (HTML卷标间的文字)<br />　　这使用lookahead及lookbehind assertion来取出HTML间的文字，不包括HTML卷标。<br /><br />　　请批注(Comments Please)<br />　　括号还有个特殊的用途就是用来包住批注，语法为&rdquo;(?#comment)&rdquo;，若设定&rdquo;Ignore Pattern Whitespace&rdquo;选项，则RE中的空格符当RE使用时会乎略。此选项设定时，&rdquo;#&rdquo;之后的文字会乎略。<br /><br />　　31. HTML卷标间的文字，加上批注<br /><br />　　(?&lt;= 　#查找前缀，但不包含它<br />　　&lt;(\w+)&gt; #HTML标签<br />　　) #结束查找前缀<br />　　.* #符合任何文字<br />　　(?= #查找字尾，但不包含它<br />　　&lt;\/\1&gt; #符合所抓取群组1之字符串，也就是前面小括号的HTML标签<br />　　) #结束查找字尾<br /><br />　　寻找最多字符的字及最少字符的字(Greedy and Lazy)<br />　　当RE下要查找一个范围的重复时(如&rdquo;.*&rdquo;)，它通常会寻找最多字符的符合字，也就是Greedy matching。举例来说。<br /><br />　　32. a.*b (开始为a结束为b的最多字符的符合字)<br /><br />　　若有一字符串是&rdquo;aabab&rdquo;，使用上述RE所得到的符合字符串就是&rdquo;aabab&rdquo;，因为这是寻找最多字符的字。有时希望是符合最少字符的字也就是lazy matching。只要将重复前述项目的表加上问号(?)就可以把它们全部变成lazy matching。因此&rdquo;*?&rdquo;代表的就是重复任意次数，但是使用最少重复的次数来符合。举个例子来说：<br /><br />　　33. a.*?b (开始为a结束为b的最少字符的符合字)<br /><br />　　若有一字符串是&rdquo;aabab&rdquo;，使用上述RE第一个所得到的符合字符串就是&rdquo;aab&rdquo;再来是&rdquo;ab&rdquo;，因为这是寻找最少字符的字。<br /><br />　　*? 重复任意次数，最少重复次数为原则<br />　　+? 重复至少一次，最少重复次数为原则<br />　　?? 重复零次或一次，最少重复次数为原则<br />　　{n,m}? 重复至少n次，但不超过m次，最少重复次数为原则<br />　　{n,}? 重复至少n次，最少重复次数为原则<br /><br />还有什么没提到呢?<br /><br />　　到目前为止，已经提到了许多建立RE的元素，当然还有许多元素没有提到，下表整理了一些没提到的元素，在最左边的字段的数字是说明在Expresso中的例子。<br /><br />　　# 语法 说明<br /><br />　　\a Bell 字符<br />　　\b 通常是指字的边界，在字符组里所代表的就是backspace<br />　　\t Tab<br /><br />　　34 \r Carriage return<br /><br />　　\v Vertical Tab<br />　　\f From feed<br /><br />　　35 \n New line<br />　　\e Escape<br /><br />　　36 \nnn ASCII八位码为nnn的字符<br /><br />　　37 \xnn 十六位码为nn的字符<br /><br />　　38 \unnnn Unicode为nnnn的字符<br /><br />　　39 \cN Control N字符，举例来说Ctrl-M是\cM<br /><br />　　40 \A 字符串的开始(和^相似，但不需籍由multiline选项)<br /><br />　　41 \Z 字符串的结尾<br />　　\z 字符串的结尾<br /><br />　　42 \G 目前查找的开始<br /><br />　　43 \p{name} Unicode 字符组名称为name的字符，比如说\p{Lowercase_Letter} 所指的就是小写字<br />　　(?&gt;exp) Greedy次描述，又称之为non-backtracking次描述。这只符合一次且不采backtracking。<br /><br />　　44 (?&lt;x&gt;-&lt;y&gt;exp)<br /><br />　　or (?-&lt;y&gt;exp) 平衡群组。虽复杂但好用。它让已命名的抓取群组可以在堆栈中操作使用。(小弟对这个也是不太懂哩)<br /><br />　　45 (?im-nsx:exp) 为次描述exp更改RE选项，比如(?-i:Elvis)就是把Elvis大乎略大小写的选项关掉<br /><br />　　46 (?im-nsx) 为之后的群组更改RE选项。<br />　　(?(exp)yes|no) 次描述exp视为zero-width positive lookahead。若此时有符合，则yes次描述为下一个符合标的，若否，则no 次描述为下一个符合标的。<br />　　(?(exp)yes) 和上述相同但无no次描述<br />　　(?(name)yes|no) 若name群组为有效群组名称，则yes次描述为下一个符合标的，若否，则no 次描述为下一个符合标的。<br /><br />　　47 (?(name)yes) 和上述相同但无no次描述 <br /><br /><br /><font size="2">From:Internet &nbsp; <br />想必很多人都对正则表达式都头疼.今天,我以我的认识,加上网上一些文章,希望用常人都可以理解的表达方式.来和大家分享学习经验.<br /><br />开篇,还是得说说 ^ 和 $ 他们是分别用来匹配字符串的开始和结束，以下分别举例说明 <br /><br /><br />&quot;^The&quot;: 开头一定要有&quot;The&quot;字符串; <br />&quot;of despair$&quot;: 结尾一定要有&quot;of despair&quot; 的字符串; <br /><br /><br />那么,<br />&quot;^abc$&quot;: 就是要求以abc开头和以abc结尾的字符串，实际上是只有abc匹配 <br />&quot;notice&quot;: 匹配包含notice的字符串 <br /><br /><br />你可以看见如果你没有用我们提到的两个字符（最后一个例子），就是说 模式（正则表达式） 可以出现在被检验字符串的任何地方，你没有把他锁定到两边 <br /><br />接着,说说 '*', '+',和 '?', <br />他们用来表示一个字符可以出现的次数或者顺序. 他们分别表示：<br />&quot;zero or more&quot;相当于{0,}, <br />&quot;one or more&quot;相当于{1,}, <br />&quot;zero or one.&quot;相当于{0,1}, 这里是一些例子: <br /><br /><br />&quot;ab*&quot;: 和ab{0,}同义,匹配以a开头,后面可以接0个或者N个b组成的字符串(&quot;a&quot;, &quot;ab&quot;, &quot;abbb&quot;, 等); <br />&quot;ab+&quot;: 和ab{1,}同义,同上条一样，但最少要有一个b存在 (&quot;ab&quot;, &quot;abbb&quot;, 等.); <br />&quot;ab?&quot;:和ab{0,1}同义,可以没有或者只有一个b; <br />&quot;a?b+$&quot;: 匹配以一个或者0个a再加上一个以上的b结尾的字符串. <br /><br />要点, '*', '+',和 '?'只管它前面那个字符.<br /><br /><br />你也可以在大括号里面限制字符出现的个数，比如 <br /><br /><br />&quot;ab{2}&quot;: 要求a后面一定要跟两个b（一个也不能少）(&quot;abb&quot;); <br />&quot;ab{2,}&quot;: 要求a后面一定要有两个或者两个以上b(如&quot;abb&quot;, &quot;abbbb&quot;, 等.); <br />&quot;ab{3,5}&quot;: 要求a后面可以有2－5个b(&quot;abbb&quot;, &quot;abbbb&quot;, or &quot;abbbbb&quot;). <br /><br /><br /><br />现在我们把一定几个字符放到小括号里，比如：<br /><br />&quot;a(bc)*&quot;: 匹配 a 后面跟0个或者一个&quot;bc&quot;; <br />&quot;a(bc){1,5}&quot;: 一个到5个 &quot;bc.&quot; <br /><br /><br />还有一个字符 '│', 相当于OR 操作: <br /><br /><br />&quot;hi│hello&quot;: 匹配含有&quot;hi&quot; 或者 &quot;hello&quot; 的 字符串; <br />&quot;(b│cd)ef&quot;: 匹配含有 &quot;bef&quot; 或者 &quot;cdef&quot;的字符串; <br />&quot;(a│b)*c&quot;: 匹配含有这样多个（包括0个）a或b，后面跟一个c <br />的字符串; <br /><br /><br />一个点('.')可以代表所有的单一字符,不包括&quot;\n&quot;<br /><br />如果,要匹配包括&quot;\n&quot;在内的所有单个字符,怎么办?<br /><br />对了,用'[\n.]'这种模式.<br /><br /><br />&quot;a.[0-9]&quot;: 一个a加一个字符再加一个0到9的数字 <br />&quot;^.{3}$&quot;: 三个任意字符结尾 . <br /><br /><br /><br /><br />中括号括住的内容只匹配一个单一的字符 <br /><br /><br />&quot;[ab]&quot;: 匹配单个的 a 或者 b ( 和 &quot;a│b&quot; 一样); <br />&quot;[a-d]&quot;: 匹配'a' 到'd'的单个字符 (和&quot;a│b│c│d&quot; 还有 &quot;[abcd]&quot;效果一样); 一般我们都用[a-zA-Z]来指定字符为一个大小写英文<br />&quot;^[a-zA-Z]&quot;: 匹配以大小写字母开头的字符串 <br />&quot;[0-9]%&quot;: 匹配含有 形如 x％ 的字符串 <br />&quot;,[a-zA-Z0-9]$&quot;: 匹配以逗号再加一个数字或字母结尾的字符串 <br /><br /><br />你也可以把你不想要得字符列在中括号里，你只需要在总括号里面使用'^' 作为开头 &quot;%[^a-zA-Z]%&quot; 匹配含有两个百分号里面有一个非字母的字符串. <br /><br />要点:^用在中括号开头的时候,就表示排除括号里的字符 <br /><br />为了PHP能够解释，你必须在这些字符面前后加'',并且将一些字符转义. <br /><br />不要忘记在中括号里面的字符是这条规路的例外&mdash;在中括号里面, 所有的特殊字符，包括(''), 都将失去他们的特殊性质 &quot;[*\+?{}.]&quot;匹配含有这些字符的字符串.<br /><br />还有,正如regx的手册告诉我们: &quot;如果列表里含有 ']', 最好把它作为列表里的第一个字符(可能跟在'^'后面). 如果含有'-', 最好把它放在最前面或者最后面, or 或者一个范围的第二个结束点[a-d-0-9]中间的&lsquo;-&rsquo;将有效. <br /><br />看了上面的例子,你对{n,m}应该理解了吧.要注意的是,n和m都不能为负整数,而且n总是小于m. 这样,才能 最少匹配n次且最多匹配m次. 如&quot;p{1,5}&quot;将匹配 &quot;pvpppppp&quot;中的前五个p<br /><br />下面说说以\开头的<br /><br />\b 书上说他是用来匹配一个单词边界,就是...比如've\b',可以匹配love里的ve而不匹配very里有ve<br /><br />\B 正好和上面的\b相反.例子我就不举了<br /><br />.....突然想起来....可以到</font><a href="http://www.phpv.net/article.php/251" target="_blank"><font color="#000080" size="2">http://www.phpv.net/article.php/251</font></a><font size="2"> 看看其它用\ 开头的语法<br /><br /><br /><br />好,我们来做个应用:<br /><br />如何构建一个模式来匹配 货币数量 的输入 <br /><br />构建一个匹配模式去检查输入的信息是否为一个表示money的数字。我们认为一个表示money的数量有四种方式： &quot;10000.00&quot; 和 &quot;10,000.00&quot;,或者没有小数部分, &quot;10000&quot; and &quot;10,000&quot;. 现在让我们开始构建这个匹配模式: <br /><br />^[1-9][0-9]*$ <br /><br />这是所变量必须以非0的数字开头.但这也意味着 单一的 &quot;0&quot; 也不能通过测试. 以下是解决的方法: <br /><br />^(0│[1-9][0-9]*)$ <br /><br />&quot;只有0和不以0开头的数字与之匹配&quot;，我们也可以允许一个负号在数字之前: <br /><br />^(0│-?[1-9][0-9]*)$ <br /><br />这就是: &quot;0 或者 一个以0开头 且可能 有一个负号在前面的数字.&quot; 好了,现在让我们别那么严谨，允许以0开头.现在让我们放弃 负号 , 因为我们在表示钱币的时候并不需要用到. 我们现在指定 模式 用来匹配小数部分: <br /><br />^[0-9]+(\.[0-9]+)?$ <br /><br />这暗示匹配的字符串必须最少以一个阿拉伯数字开头. 但是注意，在上面模式中 &quot;10.&quot; 是不匹配的, 只有 &quot;10&quot; 和 &quot;10.2&quot; 才可以. （你知道为什么吗） <br /><br />^[0-9]+(\.[0-9]{2})?$ <br /><br />我们上面指定小数点后面必须有两位小数.如果你认为这样太苛刻,你可以改成: <br /><br />^[0-9]+(\.[0-9]{1,2})?$ <br /><br />这将允许小数点后面有一到两个字符. 现在我们加上用来增加可读性的逗号（每隔三位）, 我们可以这样表示: <br /><br />^[0-9]{1,3}(,[0-9]{3})*(\.[0-9]{1,2})?$ <br /><br />不要忘记 '+' 可以被 '*' 替代 如果你想允许空白字符串被输入话 (为什么?). 也不要忘记反斜杆 &rsquo;\&rsquo; 在php字符串中可能会出现错误 (很普遍的错误). <br /><br />现在，我们已经可以确认字符串了, 我们现在把所有逗号都去掉 str_replace(&quot;,&quot;, &quot;&quot;, $money) 然后在把类型看成 double然后我们就可以通过他做数学计算了. <br /><br /><br />再来一个:<br /><br />构造检查email的正则表达式 <br /><br />在一个完整的email地址中有三个部分: <br />1. 用户名 (在 '@' 左边的一切), <br />2.'@',<br />3. 服务器名(就是剩下那部分). <br /><br />用户名可以含有大小写字母阿拉伯数字,句号 ('.'), 减号('-'), and 下划线 ('_'). 服务器名字也是符合这个规则,当然下划线除外. <br /><br />现在, 用户名的开始和结束都不能是句点. 服务器也是这样. 还有你不能有两个连续的句点他们之间至少存在一个字符，好现在我们来看一下怎么为用户名写一个匹配模式: <br /><br />^[_a-zA-Z0-9-]+$ <br /><br />现在还不能允许句号的存在. 我们把它加上: <br /><br />^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*$ <br /><br />上面的意思就是说: &quot;以至少一个规范字符（除了.）开头,后面跟着0个或者多个以点开始的字符串.&quot; <br /><br />简单化一点, 我们可以用 eregi()取代 ereg().eregi()对大小写不敏感, 我们就不需要指定两个范围 &quot;a-z&quot; 和 &quot;A-Z&quot; &ndash; 只需要指定一个就可以了: <br /><br />^[_a-z0-9-]+(\.[_a-z0-9-]+)*$ <br /><br />后面的服务器名字也是一样,但要去掉下划线: <br /><br />^[a-z0-9-]+(\.[a-z0-9-]+)*$ <br /><br />好. 现在只需要用&rdquo;@&rdquo;把两部分连接: <br /><br />^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$ <br /><br /><br />这就是完整的email认证匹配模式了,只需要调用 <br /><br />eregi(&lsquo;^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$ &rsquo;,$eamil) <br /><br />就可以得到是否为email了 <br />正则表达式的其他用法 <br /><br />提取字符串 <br /><br />ereg() and eregi() 有一个特性是允许用户通过正则表达式去提取字符串的一部分(具体用法你可以阅读手册). 比如说,我们想从 path/URL 提取文件名 &ndash; 下面的代码就是你需要: <br /><br />ereg(&quot;([^\\/]*)$&quot;, $pathOrUrl, $regs); <br />echo $regs[1]; <br /><br />高级的代换 <br /><br />ereg_replace() 和 eregi_replace()也是非常有用的: 假如我们想把所有的间隔负号都替换成逗号: <br /><br /><br />ereg_replace(&quot;[ \n\r\t]+&quot;, &quot;,&quot;, trim($str));<br /><br />最后,我把另一串检查EMAIL的正则表达式让看文章的你来分析一下.<br /><br />&quot;^[-!#$%&amp;\'*+\\./0-9=?A-Z^_`a-z{|}~]+'.'@'.'[-!#$%&amp;\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.'[-!#$%&amp;\'*+\\./0-9=?A-Z^_`a-z{|}~]+$&quot;<br /><br />如果能方便的读懂,那这篇文章的目的就达到了.</font> <br />]]></description>
			<link>http://www.shixiang.info/?action=show&amp;id=256</link>
			<category domain="http://www.shixiang.info/?cid=2">php学习</category>
			<pubDate>2007-10-31 14:55</pubDate>
		</item>
		<item>
			<guid>http://www.shixiang.info/?action=show&amp;id=255</guid>
			<title>正则表达式收藏（二）之入门</title>
			<author>jiashixiang</author>
			<description><![CDATA[<div class="postText">
<p style="FONT-FAMILY: Times New Roman">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 什么是正则表达式<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">基本说来，正则表达式是一种用来描述一定数量文本的模式。Regex代表Regular Express。本文将用&lt;&lt;regex&gt;&gt;来表示一段具体的正则表达式。</p>
<p style="FONT-FAMILY: Times New Roman">一段文本就是最基本的模式，简单的匹配相同的文本。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不同的正则表达式引擎<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">正则表达式引擎是一种可以处理正则表达式的软件。通常，引擎是更大的应用程序的一部分。在软件世界，不同的正则表达式并不互相兼容。本教程会集中讨论Perl 5 类型的引擎，因为这种引擎是应用最广泛的引擎。同时我们也会提到一些和其他引擎的区别。许多近代的引擎都很类似，但不完全一样。例如.NET正则库，JDK正则包。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文字符号<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">最基本的正则表达式由单个文字符号组成。如&lt;&lt;a&gt;&gt;，它将匹配字符串中第一次出现的字符&ldquo;a&rdquo;。如对字符串&ldquo;Jack is a boy&rdquo;。&ldquo;J&rdquo;后的&ldquo;a&rdquo;将被匹配。而第二个&ldquo;a&rdquo;将不会被匹配。</p>
<p style="FONT-FAMILY: Times New Roman">正则表达式也可以匹配第二个&ldquo;a&rdquo;，这必须是你告诉正则表达式引擎从第一次匹配的地方开始搜索。在文本编辑器中，你可以使用&ldquo;查找下一个&rdquo;。在编程语言中，会有一个函数可以使你从前一次匹配的位置开始继续向后搜索。</p>
<p style="FONT-FAMILY: Times New Roman">类似的，&lt;&lt;cat&gt;&gt;会匹配&ldquo;About cats and dogs&rdquo;中的&ldquo;cat&rdquo;。这等于是告诉正则表达式引擎，找到一个&lt;&lt;c&gt;&gt;，紧跟一个&lt;&lt;a&gt;&gt;，再跟一个&lt;&lt;t&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">要注意，正则表达式引擎缺省是大小写敏感的。除非你告诉引擎忽略大小写，否则&lt;&lt;cat&gt;&gt;不会匹配&ldquo;Cat&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 特殊字符<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">对于文字字符，有11个字符被保留作特殊用途。他们是：</p>
<p style="FONT-FAMILY: Times New Roman">[ ] \ ^ $ . | ? * + ( )</p>
<p style="FONT-FAMILY: Times New Roman">这些特殊字符也被称作元字符。</p>
<p style="FONT-FAMILY: Times New Roman">如果你想在正则表达式中将这些字符用作文本字符，你需要用反斜杠&ldquo;\&rdquo;对其进行换码 (escape)。例如你想匹配&ldquo;1+1=2&rdquo;，正确的表达式为&lt;&lt;1\+1=2&gt;&gt;.</p>
<p style="FONT-FAMILY: Times New Roman">需要注意的是，&lt;&lt;1+1=2&gt;&gt;也是有效的正则表达式。但它不会匹配&ldquo;1+1=2&rdquo;，而会匹配&ldquo;123+111=234&rdquo;中的&ldquo;111=2&rdquo;。因为&ldquo;+&rdquo;在这里表示特殊含义（重复1次到多次）。</p>
<p style="FONT-FAMILY: Times New Roman">在编程语言中，要注意，一些特殊的字符会先被编译器处理，然后再传递给正则引擎。因此正则表达式&lt;&lt;1\+2=2&gt;&gt;在C++中要写成&ldquo;1\\+1=2&rdquo;。为了匹配&ldquo;C:\temp&rdquo;，你要用正则表达式&lt;&lt;C:\\temp&gt;&gt;。而在C++中，正则表达式则变成了&ldquo;C:\\\\temp&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不可显示字符<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">可以使用特殊字符序列来代表某些不可显示字符：</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\t&gt;&gt;代表Tab(0x09)</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\r&gt;&gt;代表回车符(0x0D)</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\n&gt;&gt;代表换行符(0x0A)</p>
<p style="FONT-FAMILY: Times New Roman">要注意的是Windows中文本文件使用&ldquo;\r\n&rdquo;来结束一行而Unix使用&ldquo;\n&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正则表达式引擎的内部工作机制<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">知道正则表达式引擎是如何工作的有助于你很快理解为何某个正则表达式不像你期望的那样工作。</p>
<p style="FONT-FAMILY: Times New Roman">有两种类型的引擎：文本导向(text-directed)的引擎和正则导向(regex-directed)的引擎。Jeffrey Friedl把他们称作DFA和NFA引擎。本文谈到的是正则导向的引擎。这是因为一些非常有用的特性，如&ldquo;惰性&rdquo;量词(lazy quantifiers)和反向引用(backreferences)，只能在正则导向的引擎中实现。所以毫不意外这种引擎是目前最流行的引擎。</p>
<p style="FONT-FAMILY: Times New Roman">你可以轻易分辨出所使用的引擎是文本导向还是正则导向。如果反向引用或&ldquo;惰性&rdquo;量词被实现，则可以肯定你使用的引擎是正则导向的。你可以作如下测试：将正则表达式&lt;&lt;regex|regex not&gt;&gt;应用到字符串&ldquo;regex not&rdquo;。如果匹配的结果是regex，则引擎是正则导向的。如果结果是regex not，则是文本导向的。因为正则导向的引擎是&ldquo;猴急&rdquo;的，它会很急切的进行表功，报告它找到的第一个匹配 。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正则导向的引擎总是返回最左边的匹配</p>
<p style="FONT-FAMILY: Times New Roman">这是需要你理解的很重要的一点：即使以后有可能发现一个&ldquo;更好&rdquo;的匹配，正则导向的引擎也总是返回最左边的匹配。</p>
<p style="FONT-FAMILY: Times New Roman">当把&lt;&lt;cat&gt;&gt;应用到&ldquo;He captured a catfish for his cat&rdquo;，引擎先比较&lt;&lt;c&gt;&gt;和&ldquo;H&rdquo;，结果失败了。于是引擎再比较&lt;&lt;c&gt;&gt;和&ldquo;e&rdquo;，也失败了。直到第四个字符，&lt;&lt;c&gt;&gt;匹配了&ldquo;c&rdquo;。&lt;&lt;a&gt;&gt;匹配了第五个字符。到第六个字符&lt;&lt;t&gt;&gt;没能匹配&ldquo;p&rdquo;，也失败了。引擎再继续从第五个字符重新检查匹配性。直到第十五个字符开始，&lt;&lt;cat&gt;&gt;匹配上了&ldquo;catfish&rdquo;中的&ldquo;cat&rdquo;，正则表达式引擎急切的返回第一个匹配的结果，而不会再继续查找是否有其他更好的匹配。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符集<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">字符集是由一对方括号&ldquo;[]&rdquo;括起来的字符集合。使用字符集，你可以告诉正则表达式引擎仅仅匹配多个字符中的一个。如果你想匹配一个&ldquo;a&rdquo;或一个&ldquo;e&rdquo;，使用&lt;&lt;[ae]&gt;&gt;。你可以使用&lt;&lt;gr[ae]y&gt;&gt;匹配gray或grey。这在你不确定你要搜索的字符是采用美国英语还是英国英语时特别有用。相反，&lt;&lt;gr[ae]y&gt;&gt;将不会匹配graay或graey。字符集中的字符顺序并没有什么关系，结果都是相同的。</p>
<p style="FONT-FAMILY: Times New Roman">你可以使用连字符&ldquo;-&rdquo;定义一个字符范围作为字符集。&lt;&lt;[0-9]&gt;&gt;匹配0到9之间的单个数字。你可以使用不止一个范围。&lt;&lt;[0-9a-fA-F] &gt;&gt;匹配单个的十六进制数字，并且大小写不敏感。你也可以结合范围定义与单个字符定义。&lt;&lt;[0-9a-fxA-FX]&gt;&gt;匹配一个十六进制数字或字母X。再次强调一下，字符和范围定义的先后顺序对结果没有影响。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符集的一些应用</p>
<p style="FONT-FAMILY: Times New Roman">查找一个可能有拼写错误的单词，比如&lt;&lt;sep[ae]r[ae]te&gt;&gt; 或 &lt;&lt;li[cs]en[cs]e&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">查找程序语言的标识符，&lt;&lt;A-Za-z_][A-Za-z_0-9]*&gt;&gt;。(*表示重复0或多次)</p>
<p style="FONT-FAMILY: Times New Roman">查找C风格的十六进制数&lt;&lt;0[xX][A-Fa-f0-9]+&gt;&gt;。(+表示重复一次或多次)</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 取反字符集</p>
<p style="FONT-FAMILY: Times New Roman">在左方括号&ldquo;[&rdquo;后面紧跟一个尖括号&ldquo;^&rdquo;，将会对字符集取反。结果是字符集将匹配任何不在方括号中的字符。不像&ldquo;.&rdquo;，取反字符集是可以匹配回车换行符的。</p>
<p style="FONT-FAMILY: Times New Roman">需要记住的很重要的一点是，取反字符集必须要匹配一个字符。&lt;&lt;q[^u]&gt;&gt;并不意味着：匹配一个q，后面没有u跟着。它意味着：匹配一个q，后面跟着一个不是u的字符。所以它不会匹配&ldquo;Iraq&rdquo;中的q，而会匹配&ldquo;Iraq is a country&rdquo;中的q和一个空格符。事实上，空格符是匹配中的一部分，因为它是一个&ldquo;不是u的字符&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman">如果你只想匹配一个q，条件是q后面有一个不是u的字符，我们可以用后面将讲到的向前查看来解决。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符集中的元字符</p>
<p style="FONT-FAMILY: Times New Roman">需要注意的是，在字符集中只有4个 字符具有特殊含义。它们是：&ldquo;] \ ^ -&rdquo;。&ldquo;]&rdquo;代表字符集定义的结束；&ldquo;\&rdquo;代表转义；&ldquo;^&rdquo;代表取反；&ldquo;-&rdquo;代表范围定义。其他常见的元字符在字符集定义内部都是正常字符，不需要转义。例如，要搜索星号*或加号+，你可以用&lt;&lt;[+*]&gt;&gt;。当然，如果你对那些通常的元字符进行转义，你的正则表达式一样会工作得很好，但是这会降低可读性。</p>
<p style="FONT-FAMILY: Times New Roman">在字符集定义中为了将反斜杠&ldquo;\&rdquo;作为一个文字字符而非特殊含义的字符，你需要用另一个反斜杠对它进行转义。&lt;&lt;[\\x]&gt;&gt;将会匹配一个反斜杠和一个X。&ldquo;]^-&rdquo;都可以用反斜杠进行转义，或者将他们放在一个不可能使用到他们特殊含义的位置。我们推荐后者，因为这样可以增加可读性。比如对于字符&ldquo;^&rdquo;，将它放在除了左括号&ldquo;[&rdquo;后面的位置，使用的都是文字字符含义而非取反含义。如&lt;&lt;[x^]&gt;&gt;会匹配一个x或^。&lt;&lt;[]x]&gt;&gt;会匹配一个&ldquo;]&rdquo;或&ldquo;x&rdquo;。&lt;&lt;[-x]&gt;&gt;或&lt;&lt;[x-]&gt;&gt;都会匹配一个&ldquo;-&rdquo;或&ldquo;x&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符集的简写</p>
<p style="FONT-FAMILY: Times New Roman">因为一些字符集非常常用，所以有一些简写方式。</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\d&gt;&gt;代表&lt;&lt;[0-9]&gt;&gt;;</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\w&gt;&gt;代表单词字符。这个是随正则表达式实现的不同而有些差异。绝大多数的正则表达式实现的单词字符集都包含了&lt;&lt;A-Za-z0-9_]&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\s&gt;&gt;代表&ldquo;白字符&rdquo;。这个也是和不同的实现有关的。在绝大多数的实现中，都包含了空格符和Tab符，以及回车换行符&lt;&lt;\r\n&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">字符集的缩写形式可以用在方括号之内或之外。&lt;&lt;\s\d&gt;&gt;匹配一个白字符后面紧跟一个数字。&lt;&lt;[\s\d]&gt;&gt;匹配单个白字符或数字。&lt;&lt;[\da-fA-F]&gt;&gt;将匹配一个十六进制数字。</p>
<p style="FONT-FAMILY: Times New Roman">取反字符集的简写</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;[\S]&gt;&gt; = &lt;&lt;[^\s]&gt;&gt;</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;[\W]&gt;&gt; = &lt;&lt;[^\w]&gt;&gt;</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;[\D]&gt;&gt; = &lt;&lt;[^\d]&gt;&gt;</p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符集的重复</p>
<p style="FONT-FAMILY: Times New Roman">如果你用&ldquo;?*+&rdquo;操作符来重复一个字符集，你将会重复整个字符集。而不仅是它匹配的那个字符。正则表达式&lt;&lt;[0-9]+&gt;&gt;会匹配837以及222。</p>
<p style="FONT-FAMILY: Times New Roman">如果你仅仅想重复被匹配的那个字符，可以用向后引用达到目的。我们以后将讲到向后引用。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用?*或+ 进行重复<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">?：告诉引擎匹配前导字符0次或一次。事实上是表示前导字符是可选的。</p>
<p style="FONT-FAMILY: Times New Roman">+：告诉引擎匹配前导字符1次或多次</p>
<p style="FONT-FAMILY: Times New Roman">*：告诉引擎匹配前导字符0次或多次</p>
<p style="FONT-FAMILY: Times New Roman">&lt;[A-Za-z][A-Za-z0-9]*&gt;匹配没有属性的HTML标签，&ldquo;&lt;&rdquo;以及&ldquo;&gt;&rdquo;是文字符号。第一个字符集匹配一个字母，第二个字符集匹配一个字母或数字。</p>
<p style="FONT-FAMILY: Times New Roman">我们似乎也可以用&lt;[A-Za-z0-9]+&gt;。但是它会匹配&lt;1&gt;。但是这个正则表达式在你知道你要搜索的字符串不包含类似的无效标签时还是足够有效的。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 限制性重复</p>
<p style="FONT-FAMILY: Times New Roman">许多现代的正则表达式实现，都允许你定义对一个字符重复多少次。词法是：{min,max}。min和max都是非负整数。如果逗号有而max被忽略了，则max没有限制。如果逗号和max都被忽略了，则重复min次。</p>
<p style="FONT-FAMILY: Times New Roman">因此{0,}和*一样，{1，}和+ 的作用一样。</p>
<p style="FONT-FAMILY: Times New Roman">你可以用&lt;&lt;\b[1-9][0-9]{3}\b&gt;&gt;匹配1000~9999之间的数字(&ldquo;\b&rdquo;表示单词边界)。&lt;&lt;\b[1-9][0-9]{2,4}\b&gt;&gt;匹配一个在100~99999之间的数字。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意贪婪性</p>
<p style="FONT-FAMILY: Times New Roman">假设你想用一个正则表达式匹配一个HTML标签。你知道输入将会是一个有效的HTML文件，因此正则表达式不需要排除那些无效的标签。所以如果是在两个尖括号之间的内容，就应该是一个HTML标签。</p>
<p style="FONT-FAMILY: Times New Roman">许多正则表达式的新手会首先想到用正则表达式&lt;&lt; &lt;.+&gt; &gt;&gt;，他们会很惊讶的发现，对于测试字符串，&ldquo;This is a &lt;EM&gt;first&lt;/EM&gt; test&rdquo;，你可能期望会返回&lt;EM&gt;，然后继续进行匹配的时候，返回&lt;/EM&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">但事实是不会。正则表达式将会匹配&ldquo;&lt;EM&gt;first&lt;/EM&gt;&rdquo;。很显然这不是我们想要的结果。原因在于&ldquo;+&rdquo;是贪婪的。也就是说，&ldquo;+&rdquo;会导致正则表达式引擎试图尽可能的重复前导字符。只有当这种重复会引起整个正则表达式匹配失败的情况下，引擎会进行回溯。也就是说，它会放弃最后一次的&ldquo;重复&rdquo;，然后处理正则表达式余下的部分。</p>
<p style="FONT-FAMILY: Times New Roman">和&ldquo;+&rdquo;类似，&ldquo;?*&rdquo;的重复也是贪婪的。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 深入正则表达式引擎内部</p>
<p style="FONT-FAMILY: Times New Roman">让我们来看看正则引擎如何匹配前面的例子。第一个记号是&ldquo;&lt;&rdquo;，这是一个文字符号。第二个符号是&ldquo;.&rdquo;，匹配了字符&ldquo;E&rdquo;，然后&ldquo;+&rdquo;一直可以匹配其余的字符，直到一行的结束。然后到了换行符，匹配失败(&ldquo;.&rdquo;不匹配换行符)。于是引擎开始对下一个正则表达式符号进行匹配。也即试图匹配&ldquo;&gt;&rdquo;。到目前为止，&ldquo;&lt;.+&rdquo;已经匹配了&ldquo;&lt;EM&gt;first&lt;/EM&gt; test&rdquo;。引擎会试图将&ldquo;&gt;&rdquo;与换行符进行匹配，结果失败了。于是引擎进行回溯。结果是现在&ldquo;&lt;.+&rdquo;匹配&ldquo;&lt;EM&gt;first&lt;/EM&gt; tes&rdquo;。于是引擎将&ldquo;&gt;&rdquo;与&ldquo;t&rdquo;进行匹配。显然还是会失败。这个过程继续，直到&ldquo;&lt;.+&rdquo;匹配&ldquo;&lt;EM&gt;first&lt;/EM&rdquo;，&ldquo;&gt;&rdquo;与&ldquo;&gt;&rdquo;匹配。于是引擎找到了一个匹配&ldquo;&lt;EM&gt;first&lt;/EM&gt;&rdquo;。记住，正则导向的引擎是&ldquo;急切的&rdquo;，所以它会急着报告它找到的第一个匹配。而不是继续回溯，即使可能会有更好的匹配，例如&ldquo;&lt;EM&gt;&rdquo;。所以我们可以看到，由于&ldquo;+&rdquo;的贪婪性，使得正则表达式引擎返回了一个最左边的最长的匹配。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用懒惰性取代贪婪性<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">一个用于修正以上问题的可能方案是用&ldquo;+&rdquo;的惰性代替贪婪性。你可以在&ldquo;+&rdquo;后面紧跟一个问号&ldquo;?&rdquo;来达到这一点。&ldquo;*&rdquo;，&ldquo;{}&rdquo;和&ldquo;?&rdquo;表示的重复也可以用这个方案。因此在上面的例子中我们可以使用&ldquo;&lt;.+?&gt;&rdquo;。让我们再来看看正则表达式引擎的处理过程。</p>
<p style="FONT-FAMILY: Times New Roman">再一次，正则表达式记号&ldquo;&lt;&rdquo;会匹配字符串的第一个&ldquo;&lt;&rdquo;。下一个正则记号是&ldquo;.&rdquo;。这次是一个懒惰的&ldquo;+&rdquo;来重复上一个字符。这告诉正则引擎，尽可能少的重复上一个字符。因此引擎匹配&ldquo;.&rdquo;和字符&ldquo;E&rdquo;，然后用&ldquo;&gt;&rdquo;匹配&ldquo;M&rdquo;，结果失败了。引擎会进行回溯，和上一个例子不同，因为是惰性重复，所以引擎是扩展惰性重复而不是减少，于是&ldquo;&lt;.+&rdquo;现在被扩展为&ldquo;&lt;EM&rdquo;。引擎继续匹配下一个记号&ldquo;&gt;&rdquo;。这次得到了一个成功匹配。引擎于是报告&ldquo;&lt;EM&gt;&rdquo;是一个成功的匹配。整个过程大致如此。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 惰性扩展的一个替代方案<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">我们还有一个更好的替代方案。可以用一个贪婪重复与一个取反字符集：&ldquo;&lt;[^&gt;]+&gt;&rdquo;。之所以说这是一个更好的方案在于使用惰性重复时，引擎会在找到一个成功匹配前对每一个字符进行回溯。而使用取反字符集则不需要进行回溯。</p>
<p style="FONT-FAMILY: Times New Roman">最后要记住的是，本教程仅仅谈到的是正则导向的引擎。文本导向的引擎是不回溯的。但是同时他们也不支持惰性重复操作。<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用&ldquo;.&rdquo;匹配几乎任意字符<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">在正则表达式中，&ldquo;.&rdquo;是最常用的符号之一。不幸的是，它也是最容易被误用的符号之一。</p>
<p style="FONT-FAMILY: Times New Roman">&ldquo;.&rdquo;匹配一个单个的字符而不用关心被匹配的字符是什么。唯一的例外是新行符。在本教程中谈到的引擎，缺省情况下都是不匹配新行符的。因此在缺省情况下，&ldquo;.&rdquo;等于是字符集[^\n\r](Window)或[^\n]( Unix)的简写。</p>
<p style="FONT-FAMILY: Times New Roman">这个例外是因为历史的原因。因为早期使用正则表达式的工具是基于行的。它们都是一行一行的读入一个文件，将正则表达式分别应用到每一行上去。在这些工具中，字符串是不包含新行符的。因此&ldquo;.&rdquo;也就从不匹配新行符。</p>
<p style="FONT-FAMILY: Times New Roman">现代的工具和语言能够将正则表达式应用到很大的字符串甚至整个文件上去。本教程讨论的所有正则表达式实现都提供一个选项，可以使&ldquo;.&rdquo;匹配所有的字符，包括新行符。在RegexBuddy, EditPad Pro或PowerGREP等工具中，你可以简单的选中&ldquo;点号匹配新行符&rdquo;。在Perl中，&ldquo;.&rdquo;可以匹配新行符的模式被称作&ldquo;单行模式&rdquo;。很不幸，这是一个很容易混淆的名词。因为还有所谓&ldquo;多行模式&rdquo;。多行模式只影响行首行尾的锚定(anchor)，而单行模式只影响&ldquo;.&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman">其他语言和正则表达式库也采用了Perl的术语定义。当在.NET Framework中使用正则表达式类时，你可以用类似下面的语句来激活单行模式：Regex.Match(&ldquo;string&rdquo;,&rdquo;regex&rdquo;,RegexOptions.SingleLine)</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 保守的使用点号&ldquo;.&rdquo;</p>
<p style="FONT-FAMILY: Times New Roman">点号可以说是最强大的元字符。它允许你偷懒：用一个点号，就能匹配几乎所有的字符。但是问题在于，它也常常会匹配不该匹配的字符。</p>
<p style="FONT-FAMILY: Times New Roman">我会以一个简单的例子来说明。让我们看看如何匹配一个具有&ldquo;mm/dd/yy&rdquo;格式的日期，但是我们想允许用户来选择分隔符。很快能想到的一个方案是&lt;&lt;\d\d.\d\d.\d\d&gt;&gt;。看上去它能匹配日期&ldquo;02/12/03&rdquo;。问题在于02512703也会被认为是一个有效的日期。</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\d\d[-/.]\d\d[-/.]\d\d&gt;&gt;看上去是一个好一点的解决方案。记住点号在一个字符集里不是元字符。这个方案远不够完善，它会匹配&ldquo;99/99/99&rdquo;。而&lt;&lt;[0-1]\d[-/.][0-3]\d[-/.]\d\d&gt;&gt;又更进一步。尽管他也会匹配&ldquo;19/39/99&rdquo;。你想要你的正则表达式达到如何完美的程度取决于你想达到什么样的目的。如果你想校验用户输入，则需要尽可能的完美。如果你只是想分析一个已知的源，并且我们知道没有错误的数据，用一个比较好的正则表达式来匹配你想要搜寻的字符就已经足够。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">8.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符串开始和结束的锚定<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">锚定和一般的正则表达式符号不同，它不匹配任何字符。相反，他们匹配的是字符之前或之后的位置。&ldquo;^&rdquo;匹配一行字符串第一个字符前的位置。&lt;&lt;^a&gt;&gt;将会匹配字符串&ldquo;abc&rdquo;中的a。&lt;&lt;^b&gt;&gt;将不会匹配&ldquo;abc&rdquo;中的任何字符。</p>
<p style="FONT-FAMILY: Times New Roman">类似的，$匹配字符串中最后一个字符的后面的位置。所以&lt;&lt;c$&gt;&gt;匹配&ldquo;abc&rdquo;中的c。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 锚定的应用<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">在编程语言中校验用户输入时，使用锚定是非常重要的。如果你想校验用户的输入为整数，用&lt;&lt;^\d+$&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">用户输入中，常常会有多余的前导空格或结束空格。你可以用&lt;&lt;^\s*&gt;&gt;和&lt;&lt;\s*$&gt;&gt;来匹配前导空格或结束空格。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用&ldquo;^&rdquo;和&ldquo;$&rdquo;作为行的开始和结束锚定<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">如果你有一个包含了多行的字符串。例如：&ldquo;first line\n\rsecond line&rdquo;(其中\n\r表示一个新行符)。常常需要对每行分别处理而不是整个字符串。因此，几乎所有的正则表达式引擎都提供一个选项，可以扩展这两种锚定的含义。&ldquo;^&rdquo;可以匹配字串的开始位置(在f之前)，以及每一个新行符的后面位置(在\n\r和s之间)。类似的，$会匹配字串的结束位置(最后一个e之后)，以及每个新行符的前面(在e与\n\r之间)。</p>
<p style="FONT-FAMILY: Times New Roman">在.NET中，当你使用如下代码时，将会定义锚定匹配每一个新行符的前面和后面位置：Regex.Match(&quot;string&quot;, &quot;regex&quot;, RegexOptions.Multiline)</p>
<p style="FONT-FAMILY: Times New Roman">应用：string str = Regex.Replace(Original, &quot;^&quot;, &quot;&gt; &quot;, RegexOptions.Multiline)--将会在每行的行首插入&ldquo;&gt; &rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 绝对锚定<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;\A&gt;&gt;只匹配整个字符串的开始位置，&lt;&lt;\Z&gt;&gt;只匹配整个字符串的结束位置。即使你使用了&ldquo;多行模式&rdquo;，&lt;&lt;\A&gt;&gt;和&lt;&lt;\Z&gt;&gt;也从不匹配新行符。</p>
<p style="FONT-FAMILY: Times New Roman">即使\Z和$只匹配字符串的结束位置，仍然有一个例外的情况。如果字符串以新行符结束，则\Z和$将会匹配新行符前面的位置，而不是整个字符串的最后面。这个&ldquo;改进&rdquo;是由Perl引进的，然后被许多的正则表达式实现所遵循，包括Java，.NET等。如果应用&lt;&lt;^[a-z]+$&gt;&gt;到&ldquo;joe\n&rdquo;，则匹配结果是&ldquo;joe&rdquo;而不是&ldquo;joe\n&rdquo;。<br />9.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单词边界<o:p></o:p> </p>
<p style="FONT-FAMILY: Times New Roman">&nbsp;</p>
<p style="FONT-FAMILY: Times New Roman">元字符&lt;&lt;\b&gt;&gt;也是一种对位置进行匹配的&ldquo;锚&rdquo;。这种匹配是0长度匹配。</p>
<p style="FONT-FAMILY: Times New Roman">有4种位置被认为是&ldquo;单词边界&rdquo;：</p>
<p style="FONT-FAMILY: Times New Roman">1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在字符串的第一个字符前的位置(如果字符串的第一个字符是一个&ldquo;单词字符&rdquo;)</p>
<p style="FONT-FAMILY: Times New Roman">2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在字符串的最后一个字符后的位置(如果字符串的最后一个字符是一个&ldquo;单词字符&rdquo;)</p>
<p style="FONT-FAMILY: Times New Roman">3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一个&ldquo;单词字符&rdquo;和&ldquo;非单词字符&rdquo;之间，其中&ldquo;非单词字符&rdquo;紧跟在&ldquo;单词字符&rdquo;之后</p>
<p style="FONT-FAMILY: Times New Roman">4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在一个&ldquo;非单词字符&rdquo;和&ldquo;单词字符&rdquo;之间，其中&ldquo;单词字符&rdquo;紧跟在&ldquo;非单词字符&rdquo;后面</p>
<p style="FONT-FAMILY: Times New Roman">&nbsp;&ldquo;单词字符&rdquo;是可以用&ldquo;\w&rdquo;匹配的字符，&ldquo;非单词字符&rdquo;是可以用&ldquo;\W&rdquo;匹配的字符。在大多数的正则表达式实现中，&ldquo;单词字符&rdquo;通常包括&lt;&lt;[a-zA-Z0-9_]&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">例如：&lt;&lt;\b4\b&gt;&gt;能够匹配单个的4而不是一个更大数的一部分。这个正则表达式不会匹配&ldquo;44&rdquo;中的4。</p>
<p style="FONT-FAMILY: Times New Roman">换种说法，几乎可以说&lt;&lt;\b&gt;&gt;匹配一个&ldquo;字母数字序列&rdquo;的开始和结束的位置。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&ldquo;单词边界&rdquo;的取反集为&lt;&lt;\B&gt;&gt;，他要匹配的位置是两个&ldquo;单词字符&rdquo;之间或者两个&ldquo;非单词字符&rdquo;之间的位置。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 深入正则表达式引擎内部</p>
<p style="FONT-FAMILY: Times New Roman">让我们看看把正则表达式&lt;&lt;\bis\b&gt;&gt;应用到字符串&ldquo;This island is beautiful&rdquo;。引擎先处理符号&lt;&lt;\b&gt;&gt;。因为\b是0长度 ，所以第一个字符T前面的位置会被考察。因为T是一个&ldquo;单词字符&rdquo;，而它前面的字符是一个空字符(void)，所以\b匹配了单词边界。接着&lt;&lt;i&gt;&gt;和第一个字符&ldquo;T&rdquo;匹配失败。匹配过程继续进行，直到第五个空格符，和第四个字符&ldquo;s&rdquo;之间又匹配了&lt;&lt;\b&gt;&gt;。然而空格符和&lt;&lt;i&gt;&gt;不匹配。继续向后，到了第六个字符&ldquo;i&rdquo;，和第五个空格字符之间匹配了&lt;&lt;\b&gt;&gt;，然后&lt;&lt;is&gt;&gt;和第六、第七个字符都匹配了。然而第八个字符和第二个&ldquo;单词边界&rdquo;不匹配，所以匹配又失败了。到了第13个字符i，因为和前面一个空格符形成&ldquo;单词边界&rdquo;，同时&lt;&lt;is&gt;&gt;和&ldquo;is&rdquo;匹配。引擎接着尝试匹配第二个&lt;&lt;\b&gt;&gt;。因为第15个空格符和&ldquo;s&rdquo;形成单词边界，所以匹配成功。引擎&ldquo;急着&rdquo;返回成功匹配的结果。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">10.&nbsp; 选择符<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">正则表达式中&ldquo;|&rdquo;表示选择。你可以用选择符匹配多个可能的正则表达式中的一个。</p>
<p style="FONT-FAMILY: Times New Roman">如果你想搜索文字&ldquo;cat&rdquo;或&ldquo;dog&rdquo;，你可以用&lt;&lt;cat|dog&gt;&gt;。如果你想有更多的选择，你只要扩展列表&lt;&lt;cat|dog|mouse|fish&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">选择符在正则表达式中具有最低的优先级，也就是说，它告诉引擎要么匹配选择符左边的所有表达式，要么匹配右边的所有表达式。你也可以用圆括号来限制选择符的作用范围。如&lt;&lt;\b(cat|dog)\b&gt;&gt;，这样告诉正则引擎把(cat|dog)当成一个正则表达式单位来处理。</p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意正则引擎的&ldquo;急于表功&rdquo;性</p>
<p style="FONT-FAMILY: Times New Roman">正则引擎是急切的，当它找到一个有效的匹配时，它会停止搜索。因此在一定条件下，选择符两边的表达式的顺序对结果会有影响。假设你想用正则表达式搜索一个编程语言的函数列表：Get，GetValue，Set或SetValue。一个明显的解决方案是&lt;&lt;Get|GetValue|Set|SetValue&gt;&gt;。让我们看看当搜索SetValue时的结果。</p>
<p style="FONT-FAMILY: Times New Roman">因为&lt;&lt;Get&gt;&gt;和&lt;&lt;GetValue&gt;&gt;都失败了，而&lt;&lt;Set&gt;&gt;匹配成功。因为正则导向的引擎都是&ldquo;急切&rdquo;的，所以它会返回第一个成功的匹配，就是&ldquo;Set&rdquo;，而不去继续搜索是否有其他更好的匹配。</p>
<p style="FONT-FAMILY: Times New Roman">和我们期望的相反，正则表达式并没有匹配整个字符串。有几种可能的解决办法。一是考虑到正则引擎的&ldquo;急切&rdquo;性，改变选项的顺序，例如我们使用&lt;&lt;GetValue|Get|SetValue|Set&gt;&gt;，这样我们就可以优先搜索最长的匹配。我们也可以把四个选项结合起来成两个选项：&lt;&lt;Get(Value)?|Set(Value)?&gt;&gt;。因为问号重复符是贪婪的，所以SetValue总会在Set之前被匹配。</p>
<p style="FONT-FAMILY: Times New Roman">一个更好的方案是使用单词边界：&lt;&lt;\b(Get|GetValue|Set|SetValue)\b&gt;&gt;或&lt;&lt;\b(Get(Value)?|Set(Value)?\b&gt;&gt;。更进一步，既然所有的选择都有相同的结尾，我们可以把正则表达式优化为&lt;&lt;\b(Get|Set)(Value)?\b&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">11.&nbsp; 组与向后引用<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">把正则表达式的一部分放在圆括号内，你可以将它们形成组。然后你可以对整个组使用一些正则操作，例如重复操作符。</p>
<p style="FONT-FAMILY: Times New Roman">要注意的是，只有圆括号&ldquo;()&rdquo;才能用于形成组。&ldquo;[]&rdquo;用于定义字符集。&ldquo;{}&rdquo;用于定义重复操作。</p>
<p style="FONT-FAMILY: Times New Roman">当用&ldquo;()&rdquo;定义了一个正则表达式组后，正则引擎则会把被匹配的组按照顺序编号，存入缓存。当对被匹配的组进行向后引用的时候，可以用&ldquo;\数字&rdquo;的方式进行引用。&lt;&lt;\1&gt;&gt;引用第一个匹配的后向引用组，&lt;&lt;\2&gt;&gt;引用第二个组，以此类推，&lt;&lt;\n&gt;&gt;引用第n个组。而&lt;&lt;\0&gt;&gt;则引用整个被匹配的正则表达式本身。我们看一个例子。</p>
<p style="FONT-FAMILY: Times New Roman">假设你想匹配一个HTML标签的开始标签和结束标签，以及标签中间的文本。比如&lt;B&gt;This is a test&lt;/B&gt;，我们要匹配&lt;B&gt;和&lt;/B&gt;以及中间的文字。我们可以用如下正则表达式：&ldquo;&lt;([A-Z][A-Z0-9]*)[^&gt;]*&gt;.*?&lt;/\1&gt;&rdquo;</p>
<p style="FONT-FAMILY: Times New Roman">首先，&ldquo;&lt;&rdquo;将会匹配&ldquo;&lt;B&gt;&rdquo;的第一个字符&ldquo;&lt;&rdquo;。然后[A-Z]匹配B，[A-Z0-9]*将会匹配0到多次字母数字，后面紧接着0到多个非&ldquo;&gt;&rdquo;的字符。最后正则表达式的&ldquo;&gt;&rdquo;将会匹配&ldquo;&lt;B&gt;&rdquo;的&ldquo;&gt;&rdquo;。接下来正则引擎将对结束标签之前的字符进行惰性匹配，直到遇到一个&ldquo;&lt;/&rdquo;符号。然后正则表达式中的&ldquo;\1&rdquo;表示对前面匹配的组&ldquo;([A-Z][A-Z0-9]*)&rdquo;进行引用，在本例中，被引用的是标签名&ldquo;B&rdquo;。所以需要被匹配的结尾标签为&ldquo;&lt;/B&gt;&rdquo;<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">你可以对相同的后向引用组进行多次引用，&lt;&lt;([a-c])x\1x\1&gt;&gt;将匹配&ldquo;axaxa&rdquo;、&ldquo;bxbxb&rdquo;以及&ldquo;cxcxc&rdquo;。如果用数字形式引用的组没有有效的匹配，则引用到的内容简单的为空。<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">一个后向引用不能用于它自身。&lt;&lt;([abc]\1)&gt;&gt;是错误的。因此你不能将&lt;&lt;\0&gt;&gt;用于一个正则表达式匹配本身，它只能用于替换操作中。</p>
<p style="FONT-FAMILY: Times New Roman">后向引用不能用于字符集内部。&lt;&lt;(a)[\1b]&gt;&gt;中的&lt;&lt;\1&gt;&gt;并不表示后向引用。在字符集内部，&lt;&lt;\1&gt;&gt;可以被解释为八进制形式的转码。</p>
<p style="FONT-FAMILY: Times New Roman">向后引用会降低引擎的速度，因为它需要存储匹配的组。如果你不需要向后引用，你可以告诉引擎对某个组不存储。例如：&lt;&lt;Get(?:Value)&gt;&gt;。其中&ldquo;(&rdquo;后面紧跟的&ldquo;?:&rdquo;会告诉引擎对于组(Value)，不存储匹配的值以供后向引用。</p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重复操作与后向引用<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">当对组使用重复操作符时，缓存里后向引用内容会被不断刷新，只保留最后匹配的内容。例如：&lt;&lt;([abc]+)=\1&gt;&gt;将匹配&ldquo;cab=cab&rdquo;，但是&lt;&lt;([abc])+=\1&gt;&gt;却不会。因为([abc])第一次匹配&ldquo;c&rdquo;时，&ldquo;\1&rdquo;代表&ldquo;c&rdquo;；然后([abc])会继续匹配&ldquo;a&rdquo;和&ldquo;b&rdquo;。最后&ldquo;\1&rdquo;代表&ldquo;b&rdquo;，所以它会匹配&ldquo;cab=b&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman">应用：检查重复单词--当编辑文字时，很容易就会输入重复单词，例如&ldquo;the the&rdquo;。使用&lt;&lt;\b(\w+)\s+\1\b&gt;&gt;可以检测到这些重复单词。要删除第二个单词，只要简单的利用替换功能替换掉&ldquo;\1&rdquo;就可以了。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 组的命名和引用</p>
<p style="FONT-FAMILY: Times New Roman">在PHP，Python中，可以用&lt;&lt;(?P&lt;name&gt;group)&gt;&gt;来对组进行命名。在本例中，词法?P&lt;name&gt;就是对组(group)进行了命名。其中name是你对组的起的名字。你可以用(?P=name)进行引用。</p>
<p style="FONT-FAMILY: Times New Roman">.NET的命名组</p>
<p style="FONT-FAMILY: Times New Roman">.NET framework也支持命名组。不幸的是，微软的程序员们决定发明他们自己的语法，而不是沿用Perl、Python的规则。目前为止，还没有任何其他的正则表达式实现支持微软发明的语法。</p>
<p style="FONT-FAMILY: Times New Roman">下面是.NET中的例子：</p>
<p style="FONT-FAMILY: Times New Roman">(?&lt;first&gt;group)(?&rsquo;second&rsquo;group)</p>
<p style="FONT-FAMILY: Times New Roman">正如你所看到的，.NET提供两种词法来创建命名组：一是用尖括号&ldquo;&lt;&gt;&rdquo;，或者用单引号&ldquo;&rsquo;&rsquo;&rdquo;。尖括号在字符串中使用更方便，单引号在ASP代码中更有用，因为ASP代码中&ldquo;&lt;&gt;&rdquo;被用作HTML标签。</p>
<p style="FONT-FAMILY: Times New Roman">要引用一个命名组，使用\k&lt;name&gt;或\k&rsquo;name&rsquo;.</p>
<p style="FONT-FAMILY: Times New Roman">当进行搜索替换时，你可以用&ldquo;${name}&rdquo;来引用一个命名组。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">12.&nbsp; 正则表达式的匹配模式<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">本教程所讨论的正则表达式引擎都支持三种匹配模式：</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;/i&gt;&gt;使正则表达式对大小写不敏感，</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;/s&gt;&gt;开启&ldquo;单行模式&rdquo;，即点号&ldquo;.&rdquo;匹配新行符</p>
<p style="FONT-FAMILY: Times New Roman">&lt;&lt;/m&gt;&gt;开启&ldquo;多行模式&rdquo;，即&ldquo;^&rdquo;和&ldquo;$&rdquo;匹配新行符的前面和后面的位置。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在正则表达式内部打开或关闭模式</p>
<p style="FONT-FAMILY: Times New Roman">如果你在正则表达式内部插入修饰符(?ism)，则该修饰符只对其右边的正则表达式起作用。(?-i)是关闭大小写不敏感。你可以很快的进行测试。&lt;&lt;(?i)te(?-i)st&gt;&gt;应该匹配TEst，但是不能匹配teST或TEST.</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">13.&nbsp; 原子组与防止回溯<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">在一些特殊情况下，因为回溯会使得引擎的效率极其低下。</p>
<p style="FONT-FAMILY: Times New Roman">让我们看一个例子：要匹配这样的字串，字串中的每个字段间用逗号做分隔符，第12个字段由P开头。</p>
<p style="FONT-FAMILY: Times New Roman">我们容易想到这样的正则表达式&lt;&lt;^(.*?,){11}P&gt;&gt;。这个正则表达式在正常情况下工作的很好。但是在极端情况下，如果第12个字段不是由P开头，则会发生灾难性的回溯。如要搜索的字串为&ldquo;1,2,3,4,5,6,7,8,9,10,11,12,13&rdquo;。首先，正则表达式一直成功匹配直到第12个字符。这时，前面的正则表达式消耗的字串为&ldquo;1,2,3,4,5,6,7,8,9,10,11,&rdquo;，到了下一个字符，&lt;&lt;P&gt;&gt;并不匹配&ldquo;12&rdquo;。所以引擎进行回溯，这时正则表达式消耗的字串为&ldquo;1,2,3,4,5,6,7,8,9,10,11&rdquo;。继续下一次匹配过程，下一个正则符号为点号&lt;&lt;.&gt;&gt;，可以匹配下一个逗号&ldquo;,&rdquo;。然而&lt;&lt;，&gt;&gt;并不匹配字符&ldquo;12&rdquo;中的&ldquo;1&rdquo;。匹配失败，继续回溯。大家可以想象，这样的回溯组合是个非常大的数量。因此可能会造成引擎崩溃。<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">用于阻止这样巨大的回溯有几种方案：</p>
<p style="FONT-FAMILY: Times New Roman">一种简单的方案是尽可能的使匹配精确。用取反字符集代替点号。例如我们用如下正则表达式&lt;&lt;^([^,\r\n]*,){11}P&gt;&gt;，这样可以使失败回溯的次数下降到11次。</p>
<p style="FONT-FAMILY: Times New Roman">另一种方案是使用原子组。</p>
<p style="FONT-FAMILY: Times New Roman">原子组的目的是使正则引擎失败的更快一点。因此可以有效的阻止海量回溯。原子组的语法是&lt;&lt;(?&gt;正则表达式)&gt;&gt;。位于(?&gt;)之间的所有正则表达式都会被认为是一个单一的正则符号。一旦匹配失败，引擎将会回溯到原子组前面的正则表达式部分。前面的例子用原子组可以表达成&lt;&lt;^(?&gt;(.*?,){11})P&gt;&gt;。一旦第十二个字段匹配失败，引擎回溯到原子组前面的&lt;&lt;^&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">14.&nbsp; 向前查看与向后查看<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">Perl 5 引入了两个强大的正则语法：&ldquo;向前查看&rdquo;和&ldquo;向后查看&rdquo;。他们也被称作&ldquo;零长度断言&rdquo;。他们和锚定一样都是零长度的（所谓零长度即指该正则表达式不消耗被匹配的字符串）。不同之处在于&ldquo;前后查看&rdquo;会实际匹配字符，只是他们会抛弃匹配只返回匹配结果：匹配或不匹配。这就是为什么他们被称作&ldquo;断言&rdquo;。他们并不实际消耗字符串中的字符，而只是断言一个匹配是否可能。</p>
<p style="FONT-FAMILY: Times New Roman">几乎本文讨论的所有正则表达式的实现都支持&ldquo;向前向后查看&rdquo;。唯一的一个例外是Javascript只支持向前查看。</p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 肯定和否定式的向前查看<o:p></o:p></p>
<p style="FONT-FAMILY: Times New Roman">如我们前面提过的一个例子：要查找一个q，后面没有紧跟一个u。也就是说，要么q后面没有字符，要么后面的字符不是u。采用否定式向前查看后的一个解决方案为&lt;&lt;q(?!u)&gt;&gt;。否定式向前查看的语法是&lt;&lt;(?!查看的内容)&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">肯定式向前查看和否定式向前查看很类似：&lt;&lt;(?=查看的内容)&gt;&gt;。</p>
<p style="FONT-FAMILY: Times New Roman">如果在&ldquo;查看的内容&rdquo;部分有组，也会产生一个向后引用。但是向前查看本身并不会产生向后引用，也不会被计入向后引用的编号中。这是因为向前查看本身是会被抛弃掉的，只保留匹配与否的判断结果。如果你想保留匹配的结果作为向后引用，你可以用&lt;&lt;(?=(regex))&gt;&gt;来产生一个向后引用。</p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 肯定和否定式的先后查看</p>
<p style="FONT-FAMILY: Times New Roman">向后查看和向前查看有相同的效果，只是方向相反</p>
<p style="FONT-FAMILY: Times New Roman">否定式向后查看的语法是：&lt;&lt;(?&lt;!查看内容)&gt;&gt;</p>
<p style="FONT-FAMILY: Times New Roman">肯定式向后查看的语法是：&lt;&lt;(?&lt;=查看内容)&gt;&gt;</p>
<p style="FONT-FAMILY: Times New Roman">我们可以看到，和向前查看相比，多了一个表示方向的左尖括号。</p>
<p style="FONT-FAMILY: Times New Roman">例：&lt;&lt;(?&lt;!a)b&gt;&gt;将会匹配一个没有&ldquo;a&rdquo;作前导字符的&ldquo;b&rdquo;。</p>
<p style="FONT-FAMILY: Times New Roman">值得注意的是：向前查看从当前字符串位置开始对&ldquo;查看&rdquo;正则表达式进行匹配；向后查看则从当前字符串位置开始先后回溯一个字符，然后再开始对&ldquo;查看&rdquo;正则表达式进行匹配。</p>
<p style="FONT-FAMILY: Times New Roman"><o:p>&nbsp;</o:p></p>
<p style="FONT-FAMILY: Times New Roman">&middot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 深入正则表达式引擎内部</p>
<p style="FONT-FAMILY: Times New Roman">让我们看一个简单例子。</p>
<p style="FONT-FAMILY: Times New Roman">把正则表达式&lt;&lt;q(?!u)&gt;&gt;应用到字符串&ldquo;Iraq&rdquo;。正则表达式的第一个符号是&lt;&lt;q&gt;&gt;。正如我们知道的，引擎在匹配&lt;&lt;q&gt;&gt;以前会扫过整个字符串。当第四个字符&ldquo;q&rdquo;被匹配后，&ldquo;q&rdquo;后面是空字符(void)。而下一个正则符号是向前查看。引擎注意到已经进入了一个向