【野路子】正则表达式~极速入门图文教程

【野路子】正则表达式~极速学习javascript

本教程适合正则新手、初学者、看完能就用的人群。php

怎么入门呢?

网上的教程太多太多了,零散的也比较多,视频教程看起来更佳。可是整个过程比较漫长枯燥,可能暂时和你的需求目标不太一致,有些学不致用的样子。或者是问人、问百度最后搞出来了,可到了下次须要用到的时候,又进入萌逼状态了。html

正则表达式是一个什么东西呢?

若是你停留在这个问题上,这个教程可能对你做用不大。须要了解的话,详细查阅百科。java

这里只说一点:正则表达式在不少计算机程序设计语言上均可以进行匹配字符串的一种模式。python

每每用到的状况以下:数据校验、采集程序、爬虫程序,或者说我就想从目标数据拿到我想要的信息。正则表达式

 

开始了

若是你作好准备了,那么如下将以经常使用的两种语言进行讲述。chrome

Js、PHPswift

首先来看个例程:ruby

1.获取开源中国首页基本信息 

https://www.oschina.net/函数

如:title、description、keywords

怎么获取源码就不说了,右键查看源代码等,相似问题后面再也不提起。

 

a. 匹个title 入个门

在线测试正则表达式地址:http://tool.oschina.net/regex/

能够看到源码中的目标数据如横线所标。咱们只须要匹配到对应的内容便可以。

首先将对应的数据信息包括固定数据本来复制出来。

标题:<title>开源中国 - 找到您想要的开源项目,分享和交流</title>

描述:<meta name="description" itemprop="description" content="开源中国 www.oschina.net 是目前中国最大的开源技术社区。咱们传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。, 开源中国社区">

关键词:<meta name="keywords" content="开源,OSC,开源软件,开源硬件,开源网站,开源社区,java开源,perl开源,python开源,ruby开源,php开源,开源项目,开源代码">

举例测试标题,复制到在线测试正则里面进行调试。

很显然咱们匹配到结果了,这个正则表达式中能够认为不存在任何 正则表达式的语法,刚才的过程只是至关于 正常的字符串匹配。

咱们继续,删除部分数据(删除可变的数据),用正则表达式语法代替。

正则表达式的书写原则也就是:用正则语法替换可变的数据

语法:

\s 空格换行等字符

\S 非空格换行等字符

根据这个,那么咱们将其中的内容替换下。

<title>开源中国 - 找到您想要的开源项目,分享和交流</title>

改成:

<title>开源中国\s-\s找到您想要的开源项目,分享和交流</title>

测试是否能匹配经过。

很显然,咱们匹配到了。继续改进。

其中的中文字符以及逗号都是属于 “非空格”,因此咱们能够经过\S代替。继续替换并测试。

<title>开源中国\s-\s找到您想要的开源项目,分享和交流</title>

改成:

<title>\S\S\S\S\s-\s\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S</title>

依然能匹配到,貌似有些乱,容易出错,咱们继续改进。

语法:

* 对前一个语法进行0个或屡次匹配

+ 对前一个语法进行1次以上的匹配

{n,m} 指定次数匹配,如 \s{2,10}   即匹配2个到10个空格(区间都可)

{n}     指定次数匹配,如 \s{10} 即匹配10个空格

{n,}    指定次数匹配,如 \s{10,} 即匹配10个及10个以上空格(无上限)

此时终于能够将那一堆\S代替了,简直美观。

<title>\S\S\S\S\s-\s\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S\S</title>

改成:

<title>\S+\s-\s\S+</title>

或

<title>\S*\s-\s\S*</title>

或

<title>\S{4}\s-\s\S{16}</title>

除此以外还有方法匹配到吗?

固然,如

<title>开源中国 - 找到您想要的开源项目,分享和交流</title>

例1:
<title>[\u4e00-\u9fa5]+\s-\s[\u4e00-\u9fa5]+,[\u4e00-\u9fa5]+</title>

例2:
<title>[^<]+</title>

普及下语法:

语法:

[\u4e00-\u9fa5]  中文字符  ,以及双字节中文 [^\x00-\xff],PHP中语法为[\x{4e00}-\x{9fa5}]

^    ‘非’逻辑符

[]  匹配的字符范围 如[abc] ,只匹配a c 这三个字符

上面第一个正则,很显然不须要解释,[\u4e00-\u9fa5] 这个组合是匹配中文字符的,+就是进行多个匹配。

第二个正则很简洁,什么意思呢。

[<]  只匹配 <  (左键括号)

[^<]  这里的^(非逻辑)起到的做用让这个组合变成了,只匹配 非< ,也就是说只要不是< 均可以匹配。

[^<]+ 屡次匹配,直到将非<字符匹配完中止。

 

<title>[^<]+</title>

此时再看这个式子,很明显了,将两个title 标记中间的全部内容匹配完,也就是咱们须要的内容。

 

b. 描述信息如何匹配?

本来数据:

<meta name="description" itemprop="description" content="开源中国 www.oschina.net 是目前中国最大的开源技术社区。咱们传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。, 开源中国社区">

通过以上的学习,咱们能够书写几个式子,如

式1:
<meta name="description" itemprop="description" content="[^"]+">

式2:
<meta\s+name="description"\s+itemprop="[^"]+"\s+content="[^"]+">

式3:(错误)
<meta\s+name="[^"]+"\s+itemprop="[^"]+"\s+content="[^"]+">

以上3个式子,第一个第二个都很容易理解,仔细看就能看明白。

为何第三个式子错了呢?他不能匹配数据吗?答案是能够的。

在书写正则表达式的过程当中,每每不要忘了咱们的目的,以及下降可错性。

 

咱们举例下,第三个式子可能会匹配到什么数据?

式3:
<meta\s+name="[^"]+"\s+itemprop="[^"]+"\s+content="[^"]+">


数据1:
<meta name="description" itemprop="description" content="开源中国 www.oschina.net 是目前中国最大的开源技术社区。咱们传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。, 开源中国社区">


数据2:
<meta name="robots" itemprop="robots" content="index, follow">

数据3:
<meta name="viewport" itemprop="viewport" content="width=device-width, initial-scale=1">

以上三条数据,数据1是咱们的意愿数据,但2和3不是,这就产生出错了。这并非咱们所想要的。

上面的数据只是举例测试,不是开源中国的数据。

因此在写正则的时候,必定要有标志性的固定字符,如上面的 name="description" 

c.匹配关键词

这里都不用写式子了,相信各位均可以很轻易的完成。

本来数据:

<meta name="keywords" content="开源,OSC,开源软件,开源硬件,开源网站,开源社区,java开源,perl开源,python开源,ruby开源,php开源,开源项目,开源代码">


式子:
<meta\s+name="keywords"\s+content="[^"]+">

 

d.用代码实现

使用chrome 打开开源中国,按F12 DevTools调试,选择Console控制台执行JS。

js

var html = document.documentElement.outerHTML;
html.match(/<title>[^<]+<\/title>/);

//注意上面  <\/title>  多了一个反斜杠\ ,咱们要将正斜杠/ 转义掉,不然影响正则表达式。
//两边的 /是什么呢?这个是正则表达式的定界符,表示中间的内容为正则主要匹配数据、模式。

结果里面包含了title标签,也就是固定字符,这并非咱们的预期,如何解决呢?

语法:

()  子匹配其中的内容,如 <title>([^<]+)</title>

修正代码

html.match(/<title>([^<]+)<\/title>/);
html.match(/<title>([^<]+)<\/title>/)[1];

测试以下

很简单就取到咱们的结果。

JS的另外一种写法:

var regular = new RegExp('<title>([^<]+)</title>');
html.match(regular);

PHP

<?php
$html = file_get_contents('https://www.oschina.net/');

$pattern = '/<title>([^<]+)<\/title>/';
preg_match_all($pattern, $html,$result);
echo '<pre>';
print_r($result);

2.练习,匹配开源中国资讯条目

JS

html.match(/<div class="box vertical news">[^<]+<a\s+class="[^"]+"\s+href="([^"]+)"[^>]+>([^<]+)<\/a>[^<]+<span\s+class="box-fr news-date">([^<]+)<\/span>\s+<\/div>/)

很不巧的是,智能匹配到1个,那么剩下的数据为何没有匹配到呢?

由于match这个函数默认只返回第一次匹配的结果,不会返回全部匹配到的结果。

语法:

g 修饰符,全文匹配全部结果

修饰符用法:

/ 正则表达式 /修饰符

如: /<li[^>]+>([^<]+)<\/li>/g      全文匹配全部li

如如下便可匹配到全部的条目。 

html.match(/<div class="box vertical news">[^<]+<a\s+class="[^"]+"\s+href="([^"]+)"[^>]+>([^<]+)<\/a>[^<]+<span\s+class="box-fr news-date">([^<]+)<\/span>\s+<\/div>/g);

 

PHP

<?php
$html = file_get_contents('https://www.oschina.net/');

$pattern = '/<div class="box vertical news">[^<]+<a\s+class="[^"]+"\s+href="([^"]+)"[^>]+>([^<]+)<\/a>[^<]+<span\s+class="box-fr news-date">([^<]+)<\/span>\s+<\/div>/';
preg_match_all($pattern, $html,$result);
echo '<pre>';
print_r($result);

而对于PHP而言,就不须要g了,区别于函数的选择上。

perg_match 单次匹配

preg_match_all  全部匹配

 

 

补充学习

经过以上的学习,一些简单基本的正则匹配均可以实现。

那么再补充说一说常规数据校验匹配的案例,虽然网上都有。

/^\d{11}$/  匹配11位数字(手机号)

^为起始匹配也就说,第一个字符必须是 \d  也就是数字,$表明结束符,一样,匹配的这段字符必须以 \d 结束才行。

/^110[0-9]{14}[0-9xX]/ 

/^110[0-9]{14}[0-9X]/i

匹配北京市的身份证号,110开头,最后一位可能为数字可能为X。两个式子均可以,区别于尾部x的大小写问题,能够写到模式里,能够写到修饰符里。

修饰符 i 表明不区分大小写

 

/[A-z_\d]+\.(jpg|png|exe)/i   文件名匹配

(jpg|png|exe)  匹配jpg 或 png  或exe  ,区别于[jpg|png|exe],中括号是单个字符匹配,圆括号是总体匹配。

\.  匹配.字符,而不是任意字符,这里被反斜杠转义。

 

(.*?) 所谓的万能正则 + 贪婪模式

. 表明任意字符

.* 表明任意字符匹配0个或者多个

.*? 表明任意字符匹配0个或者多个(最少匹配,非贪婪模式)

 

var string = 'aa<div>test1</div>bb<div>test2</div>cc';
string.match(/<div>.*<\/div>/);
string.match(/<div>.*?<\/div>/);

能够看到,第一个正则没有加? 致使执行匹配到最后一个div,而增长?的只是匹配到对等的第一个div。

这个也就是正则的贪婪模式,贪婪匹配到最后一个,加上?将取消贪婪模式,也就是非贪婪模式,默认匹配到第一个就中止。

PHP中可使用修饰符 大写U,来取消贪婪模式,如:/<div>.*<\/div>/U

 

模式修正符

PHP模式修饰符又叫模式修正符,是在正则表达式的定界符以外使用。主要用来调整正则表达式的解释,提扩展了正则表达式在匹配、替换等操做的某些功能,加强了正则的能力。

模式修正符号 功能描述
i 在和正则匹配是不区分大小写
m 将字符串视为多行。默认的正则开始“^”和结束“$”将目标字条串做为一单一的一“行”字符(甚至其中包括换行符也是如此)。若是在修饰符中加上“m”,那么开始和结束将会指点字符串的每一行的开头就是“^”结束就是“$”。
s 若是设定了这个修正符,那么,被匹配的字符串将视为一行来看,包括换行符,换行符将被视为普通字符串。
x 忽略空白,除非进行转义的不被忽略。
e 只用在preg_replace()函数中,在替换字符串中逆向引用作正常的替换,将其(即“替换字符串”)做为PHP代码求值,并用其结果来替换所搜索的字符串。
A 若是使用这个修饰符,那么表达式必须是匹配的字符串中的开头部分。好比说”/a/A”匹配”abcd”。
D 模式中的$字符权匹配目标字符的结尾。没有此选项时,若是最后一个字符是换行符的话,美圆符号也会匹配此字符以前。若是设定了修正符m则忽略此项。
E 与”m”相反,若是使用这个修饰符,那么”$”将匹配绝对字符串的结尾,而不是换行符前面,默认就打开了这个模式。
U 贪婪模式,和问号的做用差很少,最大限度的匹配就是贪婪模式。

 

整理总结

[a-z] //匹配全部的小写字母 
[A-Z] //匹配全部的大写字母 
[a-zA-Z] //匹配全部的字母 
[A-z]  //匹配全部大小写字母 以及  [\]^_'   这些玩意,详查ASCII字符表。
[0-9] //匹配全部的数字 
[0-9\.\-] //匹配全部的数字,句号和减号 
[ \f\r\t\n] //匹配全部的白字符

\d //匹配一个数字字符。等价于 [0-9]。
\D //匹配一个非数字字符。等价于 [^0-9]。
\n //匹配一个换行符。等价于 \x0a 和 \cJ。
\r //匹配一个回车符。等价于 \x0d 和 \cM。
\s //匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S //匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t //匹配一个制表符。等价于 \x09 和 \cI。

\  //转义符,若是匹配\字符,需使用 \\ 。
.  //匹配除过"\n"以外的任何字符。
?  //匹配前面的子表达式零次或一次。例如,"do(es)?" 能够匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
+  //匹配前面的子表达式一次或屡次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
*  //匹配前面的子表达式零次或屡次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
^  //匹配输入字符串的开始位置。若是设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 以后的位置。
$  //匹配输入字符串的结束位置。若是设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 以前的位置。


#修饰符
i  //忽略大小写
s  //忽略换行,当作一行匹配
U  //非贪婪模式

上面整理了一些简单经常使用的,元字符以及模式规则,这些东西能够不用一次记住,书写的时候随时来查阅参考便可,写的多了,天然就会掌握这些规则技巧,彻底不用刻意记。

 

本文引用:

PHP正则表达式模式修饰符详解

相关文章
相关标签/搜索