正则表达式通常用来描述或者匹配一系列符合某个句法规则的字符串。比如^Colou?r$ 是一个用来匹配color和colour这两个字符串的正则表达式。一枚正则表达式由字符和元字符组成。

正则表达式

百科的解释:正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

目的:

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:
判断给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)。
可以通过正则表达式,从字符串中获取我们想要的特定部分。

特点:

正则表达式的特点是:
灵活性、逻辑性和功能性非常强。
可以迅速地用极简单的方式达到字符串的复杂控制。
对于刚接触的人来说,比较晦涩难懂。
由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容。

什么是元字符?

元字符是正则表达式中具有特殊意义的字符。它们是正则表达式的基石。比如[], ^, (), {}, $, +, *等。

正则表达式的元字符:

[]

^

()

$

+

?

.

*

|

\

!

正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面会给予解释。

在最简单的情况下,一个正则表达式看上去就是一个普通的查找串。例如,正则表达式”testing”中没有包含任何元字符,它可以匹配”testing”和”testing123″等字符串,但是不能匹配”Testing”。

要想真正的用好正则表达式,正确的理解元字符是最重要的事情。下表列出了所有的元字符和对它们的一个简短的描述。

元字符描述
\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
^匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
*匹配前面的子表达式任意次。例如,zo能匹配“z”,也能匹配“zo”以及“zoo”。等价于{0,}。
+匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 [‘o’, ‘o’, ‘o’, ‘o’]
.点匹配除“\n”和”\r”之外的任何单个字符。要匹配包括“\n”和”\r”在内的任何字符,请使用像“[\s\S]”的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern)非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?<=pattern)非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等。
(?<!pattern)非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等。
x|y匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[z|f]ood”则匹配“zood”或“food”。
[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”任一字符。
[a-z]字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1_”可以匹配“1_23”中的“1_”,但不能匹配“21_3”中的“1_”。
\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
\D匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持
\f匹配一个换页符。等价于\x0c和\cL。
\n匹配一个换行符。等价于\x0a和\cJ。
\r匹配一个回车符。等价于\x0d和\cM。
\s匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S匹配任何可见字符。等价于[^ \f\n\r\t\v]。
\t匹配一个制表符。等价于\x09和\cI。
\v匹配一个垂直制表符。等价于\x0b和\cK。
\w匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的”单词”字符使用Unicode字符集。
\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。
\num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。
\p{P}小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀。中括号内的“P”表示Unicode 字符集七个字符属性之一:标点字符。
其他六个属性:
L:字母;
M:标记符号(一般不会单独出现);
Z:分隔符(比如空格、换行等);
S:符号(比如数学符号、货币符号等);
N:数字(比如阿拉伯数字、罗马数字等);
C:其他字符。
*注:此语法部分语言不支持,例:javascript。
\<
>
匹配词(word)的开始(\<)和结束(>)。例如正则表达式\<the>能够匹配字符串”for the wise”中的”the”,但是不能匹配字符串”otherwise”中的”the”。注意:这个元字符不是所有的软件都支持的。
( )将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
|将两个匹配条件进行逻辑“或”(or)运算。例如正则表达式(him|her) 匹配”it belongs to him”和”it belongs to her”,但是不能匹配”it belongs to them.”。注意:这个元字符不是所有的软件都支持的。

1、[] – 这个中括号用来匹配其内部的任何一个单字符,例如:

[a] => 匹配一个单字符,它是小写字母a.

[ab] => 匹配一个单字符,它是小写字母a或者b.

[aB] => 匹配一个单字符,它是小写字母a或者大写字母B.

[1B] => 匹配一个单字符,它是数字1或者大写字母B.

[Dog] => 匹配一个单字符:它是大写字母D,小写字母o或者小写字母g。

[123b] => 匹配一个单字符:它是数字1, 2, 3或小写字母g.

[1-3] => 匹配一个单字符,它是数字1, 2或者3。

[0-9] => 匹配一个单字符,它是一个数字。

[a-d] => 匹配一个单字符,它是小写字母a, b, c或者d。

[a-z] => 匹配一个单字符,它是一个小写字母。

[A-Z] => 匹配一个单字符,它是一个大写字母。

[home.php] => 匹配一个单字符,它是小写字母h,小写字母o,小写字母m,小写字母e,特殊字符.,小写字母p,小写字母h或者小写字母p。

2、^ – 又叫“脱字符”,用来表示一段正则表达式的开始,例如:

^Colou?r => 匹配一个样本,该样本以Color或者Colour起头。

^Nov(ember)? => 匹配一个样本,该样本以Nov或者November起头。

^elearning*.html => 匹配一个样本,该样本以elearning.html起头。

^.php => 匹配一个样本,该样本以任意php文件起头。

^product-price.php => 匹配一个样本,该样本以product-price.php起头。

脱字符跟随向右开口的中括号表示否定,例如:

[^a] => 匹配一个单字符,只要它不是小写字母a。

[^B] => 匹配一个单字符,只要它不是大写字母B。

[^1] => 匹配一个单字符,只要它是它不是数字1。

[^ab] => 匹配一个单字符,只要它不是小写字母a或b。

[^aB] => 匹配一个单字符,只要它不是小写字母a或大写字母B。

[^1B] => 匹配一个单字符,只要它不是数字1或者大写字母B。

[^Dog] => 匹配一个单字符,只要它不是大写字母D,小写字母o或者小写字母g。

[^123b] => 匹配一个单字符,只要它是它不是数字1,2,3或者小写字母b。

[^1-3] => 匹配一个单字符,只要它不是数字1,2或3。

[^0-9] => 匹配一个单字符,只要它不是数字。

[^a-z] => 匹配一个单字符,只要它不是小写字母。

[^A-Z] => 匹配一个单字符,只要它不是大写字母。

3、() – 圆括号用来匹配字符串,例如:

(a) => 匹配字符串a。

(ab) => 匹配字符串ab。

(dog) => 匹配字符串dog。

(dog123) => 匹配字符串dog123。

(0-9) => 匹配字符串0-9。

(A-Z) => 匹配字符串A-Z。

(a-z) => 匹配字符串a-z。

(123dog588) => 匹配字符串123dog588。

注意:()还被用来创造和储存变量。如:^(.*)$

4、$ – 用来标记一则表达式或者是一行的完结,例如:

Colou?r$ => 匹配一个样本,该样本以Color或者Colour结尾。

Nov(ember)?$ => 匹配一个样本,该样本以Nov或者November结尾。

elearning*.html$ => 匹配一个样本,该样本以elearning.html结尾。

*.php$ => 匹配一个样本,该样本以任意php文件结尾。

product-price.php$ => 匹配一个样本,该样本以product-price.php结尾。

5、+ – 一次或多次匹配前面的子字符,例如:

[a]+ => 一次或多次匹配小写字母a。

[dog]+ => 一次或者多次匹配小写字母d,o,或者g。

[548]+ => 一次或者多次匹配数字5,4或者8。

[0-9]+ => 一次或多次匹配数字。

[a-z]+ => 一次或多次匹配小写字母。

[^a-z]+ => 一次或者多次匹配非小写字母。

[a-zA-z]+ => 匹配任意的大小写字母组合。

[^9]+ => 一次或者多次匹配非9的字符。

6、? – 零次或一次匹配前面的字符,例如:

[a]?+ => 零次或一次匹配小写字母a。

[dog]? => 零次或者一次匹配小写字母d,o,或者g。

[^dog]? => 零次或者一次匹配非小写字母d,o或者g。

[0-9]? => 零次或多次匹配数字。

[^a-z]? => 零次或多次匹配小写字母。

注意:在正则表达式中使用?表示之前的字母或者字母组可有可无。例如:正则表达式^colou?r$同时匹配color和colour。相似地,正则表达式^Nov(ember)28th?$匹配:nov 28,november 28,Nov 28th和November 28th。

7、 . – 匹配非行尾的单字符,例如:

正则表达式Action.,Scene2匹配Action1,Scene2; Action A,Scene2; Action9,Scene2但却不匹配Action10,Scene2或者Action AB,Scene2。

8、 * – 以任意次数(包括0次)匹配前面的字符,例如:

正则表达式31*将会匹配3,31,311,3111,31111等。

9、 | – 表明逻辑或,例如:

正则表达式(His|Her)匹配字符串his或者her。

10、 \ – 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用,或一个八进制转义符,例如:

正则表达式^www.bailuze.com$匹配www.bailuze.com

11、! – 表明逻辑非。但不像^(脱字符),它只在规则和条件的开头使用。例如:

(!abc) => 匹配非字符串abc。

[!0-9] => 匹配非数字的单字符。

[!a-z] => 匹配非小写字母的单字符。

一些正则表达式

^(*.html)$ => 匹配.html前任意个数的字符并将其存入变量。

^dog$ => 匹配字符串dog。

^a+$ => 一次或多次匹配小写字母a。

^(abc)+$ => 一次或多次匹配字符串abc。

^[a-z]+$ => 一次或多次匹配小写字母。

^(abc)*$ => 以任意次数匹配字符串abc。

^a*$ => 以任意次数匹配小写字母a。

问:

找出所有以elearning开头并且包含.html扩展名的文件。

^elearning*.html$

问:

找出所有的PHP文件。

^*.php$

mod_rewrite

这是一个用C语言写的模块(功能):mod_rewrite.c。这个模块只能在Apache服务器1.2或之后的版本下工作同时被.htaccess文件执行(这是一个包含文件和文件夹配置指令和规则的ASCII文件)。通过这个模块可以:

重写URL

重定向URL

解决正则URL问题

解决热链接问题

制作定制的403和404页面

基于IP地址提交内容,益处无穷

配置指令类型

总共有9种配置指令类型:

RewriteEngine

RewriteOptions

RewriteLog

RewriteLogLevel

RewriteLock

RewriteMap

RewriteBase

RewriteRule

RewriteCond

但在这里我们只讨论三种指令:RewriteEngine, RewriteRule和RewriteCond。我至今还没发现其它的指令有什么用。但如果想知道,其它的指令也会对SEO有所帮助。

RewriteEngine

这个配置指令用来激活或关闭mod_rewrite模块。

语法:RewriteEngine on/off
默认值:RewriteEngine off

这就是为什么在.htaccess文件中我们要加入下面的代码来激活mod_rewrite模块:

Options +FollowSymLinks
RewriteEngine on

RewriteRule

这个配置指令告诉服务器将给定的语句编译成规则。

语法:Rewrite <pattern> <substitution> [FLAGS]

这里的pattern是一个正则表达式而substitution是一个URL.
FLAG可以是[R], [F], [NC], [QSA], [L], [OR]等。

[R] => 重定向。默认值为302。可以被赋予从300到400的任意数值,例如:

RewriteRule ^index\.html$/index.php [r=301]

[F] => 禁止。经常与连字符-一起使用。这个连字符告诉服务器不要进行任何替代。这个信号告诉服务器不要完成请求,同时返还一条403代码。例如:

RewriteRule ^product-price\.php$ -[F]

[NC] => 它告诉服务器在匹配样本时无视大小写。例如:

RewriteRule ^him*\.php$[nc]

[QSA] => 追加请求字符串(Query String Append)。它告诉服务器将字符串从旧的URL传递到新的。

[L] => 最后规则。这个标签告诉服务器不要再处理更多的规则了。

[OR] => 逻辑或。这个标签用于RewriteCond声明中的逻辑或。

RewriteCond

这个配置指令告诉服务器将一个给定的声明编译成立刻跟进的规则的一个条件。

这里第一个mod_rewrite将每一个URL和给定的样本进行匹配。如果没有URL符合样本,那么mod_rewrite就会执行下一条规则。如果有一条URL和样本匹配,那么mod_rewrite就会搜索相应的RewriteCond。如果没有相应的RewriteCond存在,那么匹配的URL就会被替代。

如果相应的RewriteCond存在,那么每一条RewriteCond都会以从上到下的顺序被执行。服务器会将每一条RewriteCond的测试字符串和它相应的条件样本进行匹配。如果测试字符串与相应的条件样本不匹配,那么mod_rewrite就会执行下一条规则,否则就处理下一条RewriteCond。当所有的RewriteCond都成功处理完毕时,匹配的URL会被替代。测试字符串可以是:

简单文本

RewriteRule后方引用

RewriteCond后方引用

服务器变量

RewriteRule后方引用

形式为$N,这里的N可以是从0到9的任意数字。它用来标记在RewriteRule样本中被创建的变量,例如:

Rewrite ^(.*)$/index.php/$1 [L]

RewriteCond后方引用

形式为%N,这里的N可以是从1到9的任意数字。它用来标记从最后的匹配RewriteCond创建而来的在cond样本中的变量,例如:

RewriteCond %{HTTP_HOST} ^(123\.42\.162\.7)$ 
RewriteCond %1 ^123\.42\.162\.7$
RewriteRule .........

服务器变量

语法: % {Variable_Name}

例如:

%{HTTP_HOST} => 这个变量给出服务器信息以及其IP地址。

%{HTTP_USER_AGENT} => 这个变量给出用户操作系统和浏览器信息。

%{QUERY_STRING} => 这个变量返回查询字符串。

%{HTTP_REFERRER} => 这个变量返回来源的URL。

%{REMOTE_ADDR} => 这个变量返回来源的IP地址。

实例

实例一

将所有对media文件夹的页面请求重定向到亲的页面media.html

RewriteRule ^media/$/media.html [r=301,l]

实例二

将oldaddress.html页面重定向至newaddress.html页面

RewriteRule ^oldaddress\.html$/newaddress.html [r=301,l]

实例三

将一个网址重定向至另一个网站

Redirect 301 https://www.bailuze.com/

实例四

禁止来自IP地址为12.34.56.78的访问者查看product-prices.html页面

RewriteCond %{REMOTE_ADDR} ^12\.34\.56\.78$ 
RewriteRule ^product-prices\.html$/sorry.html -[F]

实例五

将bailuze.com/index.html重定向到www.bailuze.com

RewriteCond %{REQUEST_URL} ^index\.html$ 
RewriteRule ^(.*)$ https://www.bailuze.com/$1 [r=301,l]

实例六

阻止来自IP地址为12.34.56.78的访客查看sales-demo文件夹

RewriteCond %{REMOTE_ADDR} ^12\.34\.56\.78$ 
RewriteRule ^sales-demo/$ /sorry.html -[F]

实例七

阻止来自IP地址为12.34.56.78的访客访问网站www.bailuze.com

RewriteCond %{REMOTE_ADDR} ^12\.34\.56\.78$ 
RewriteRule ^.*$/ -[F]

.htaccess

这是一个包含了文件、文件夹和整个网站的配置指令以及规则的ASCII码文件。能在一个服务器上拥有多个.htaccess文件。事实上每个文件夹和目录都能有一个.htaccess文件。当将这个文件放置在某一文件夹中时,其中的规则仅对该文件夹及其子文件夹中的文件有效。当将这个文件放置在根目录时,其中的规则适用于服务器上所有的文件夹和文件。一个有效的.htaccess文件必须包含以下两行代码:

Options +FollowSymLinks 
RewriteEngine on

以上这些正则实例与SEO息息相关,是每一个SEO都应当掌握的基本知识。