正则表达式,在 PHP 和 JavaScript 中的使用

参考资料
所有正则中的元字符含义,参考这里
在线工具及常用的正则语句

1. 正则表达式

正则表达式(Regular Expression)描述了一种字符串匹配的模式(pattern),可以用单个字符串匹配符合某个规则的字符串。包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为”元字符”)。

1) 正则表达式的意义

使用正则表达式,可以:
- 数据验证:可以验证手机号格式,邮箱格式等是否符合规则。
- 数据替换:替换符合某种规则的所有的字符串,而不是仅替换一种。
- 提取子字符串:在文本或字符串中,提取指定规则的字符串。

2) 语法

1. 限定符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。
*+ 限定符都是贪婪的,因为它们会尽可能多的匹配文字。通过在 *+? 限定符之后放置 ?,该表达式从”贪心”表达式转换为”非贪心”表达式或者最小匹配。

字符描述
*匹配前面的子表达式零次、一次或多次,等价于{0,}。例如,zo* 能匹配 zzozoozoooooooo
+匹配前面的子表达式一次或多次,等价于 {1,}。例如,zo+ 能匹配 zozoozoooo,但不能匹配 z
?匹配前面的子表达式零次或一次,等价于 {0,1}。例如,do(es)? 可以匹配 do 中的 dodoes 中的 doesdoxy 中的 do
{n}匹配确定的 n 次(非负整数)。例如,o{2} 不能匹配 Bob 中的 o,但是能匹配 food 中的 oo
{n,}至少匹配 n 次(非负整数)。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等价于 ‘o+’。’o{0,}’ 则等价于 ‘o*’。
{n,m}最少匹配 n 次且最多匹配 m 次(m 和 n 均为非负整数,且n <= m)。例如,”o{1,3}” 将匹配 “fooooood” 中的前三个 o。注意在逗号和两个数之间不能有空格。

2. 普通字符

没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。

3. 非打印字符

字符描述
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [\f\n\r\t\v]。
\S匹配任何非空白字符。等价于 [^\f\n\r\t\v]。
.匹配任何单个字符。
\d任何数字。
\D任何非数字。
\w任何单词中的字符(字母, 数字, 下划线)。
\W任何非单词中的字符(非字母、非数字且非下划线)。
\f匹配一个换页符。等价于 \x0c 和 \cL。
\n匹配一个换行符。等价于 \x0a 和 \cJ。
\r匹配一个回车符。等价于 \x0d 和 \cM。
\t匹配一个制表符。等价于 \x09 和 \cI。
\v匹配一个垂直制表符。等价于 \x0b 和 \cK。
\cx匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。

4. 特殊字符

有些符号在正则表达式中有特殊含义,比如星号 *,要匹配时必须先用反斜杠 \ 转义\* 表示星号字符。

特别字符描述
$匹配字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 \n\r
( )标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。
*匹配前面的子表达式零次或多次。
+匹配前面的子表达式一次或多次。
.匹配除换行符 \n 之外的任何单字符。
[标记一个中括号表达式的开始。
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。
\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。
例如,’\n’ 匹配换行符。
^匹配字符串的开始位置。如果在方括号表达式中使用,表示不接受该字符集合
{标记限定符表达式的开始。
|指明两项之间的一个选择。(a|b)表示 a 或 b。

5. 定位符

定位符使您能够将正则表达式固定到行首或行尾,或一个单词的开头或结尾。

定位符用来描述字符串或单词的边界,^$ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。
注意:不能将限定符与定位符一起使用。由于在紧靠换行或者字边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式。

字符描述
^匹配字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。
$匹配字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。
\b匹配一个字边界,即字与空格间的位置。
\B非字边界匹配。

示例:

示例解释
/^begin[a-z]*world$/匹配以 begin 开头,以 world 结尾的字符串
/\bCha/匹配以 Cha 开头的单词

6. 选择

用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,使相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。

其中 ?: 是非捕获元之一,还有两个非捕获元是 ?= 和 ?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。

7. 反向引用

对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 \n 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。

可以使用非捕获元字符 ?:、?= 或 ?! 来重写捕获,忽略对相关匹配的保存。

反向引用的最简单的、最有用的应用之一,是提供查找文本中两个相同的相邻单词的匹配项的能力。以下面的句子为例:
Is is the cost of of gasoline going up up?
上面的句子很显然有多个重复的单词。下面的正则表达式使用单个子表达式来查找重复的单词:

var str = "Is is the cost of of gasoline going up up";
var patt1 = /\b([a-z]+) \1\b/ig;
document.write(str.match(patt1));

3) 优先级

相同优先级的从左到右进行运算,不同优先级的运算先高后低。
下表从最高到最低说明了各种正则表达式运算符的优先级顺序:

运算符描述
\转义符
(), (?:), (?=), []圆括号和方括号
*, +, ?, {n}, {n,}, {n,m}限定符
^, $, \任何元字符、任何字符定位点和序列(即:位置和顺序)
|“或”操作字符。m|food 匹配mfood。若要匹配 moodfood,需要用括号创建子表达式`(m

4) 示例

示例解释
^hello匹配 hello 开头的字符串。
world$匹配 world 结尾的字符串。
^hello[a-zA-Z \s]*world$匹配 hello 开头,world 结尾,中间有任意多个大写、小写或
空白字符(空格,回车,换行,tab等)的字符串。
[a-z]匹配所有小写字母。
[a-zA-Z]匹配所有的字母。
[0-9]匹配所有的数字。
[ \f\r\t\n]匹配所有的白字符。
^[^0-9][0-9]$匹配第一个字符不是数字,第二个字符是数字且只有2个字符的字符串。
[^\"\']匹配除了双引号(“)和单引号(‘)之外的所有字符
.{2}匹配所有的两个字符
^a{1,3}$匹配 a,aa 或 aaa 三种情况
^[1-9][0-9]{0,}$匹配所有的正整数
^\-{0,1}[0-9]{1,}$匹配所有的整数
^[-]?[0-9]+\.?[0-9]+$匹配所有的浮点数

2. PHP 的正则表达式

1) PHP 中的正则函数

PHP 中的正则相关函数

1. preg_match 匹配正则表达式

语法:

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

参数:
$pattern:要搜索的模式,字符串类型。例如:'/[a-z]/'$subject:输入字符串。例如:'Hello World!!'$matches:可选。如果提供了参数 matches,它将被填充为搜索结果。 $matches[0]一定存在,包含完整模式匹配到的文本,就是你想要的结果。如果$pattern 指定的搜索模式中包含分组,捕获子组匹配到的文本后从$matches[1] 开始依次填充,直到放完所有子组匹配到的文本。
$flags:可以被设置为 PREG_OFFSET_CAPTURE,为匹配到的每一个参数增加索引位置。此时 $matches 数组的每一个元素都变成数组,数组中第 0 个元素放匹配到的字符串,第1个元素是该匹配字符串在目标字符串 $subject 中的偏移量。
$offset:可选参数 offset 用于 指定从目标字符串的某个位置开始搜索(单位是字节)。

返回值:
返回 pattern 的匹配次数。它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后停止搜索。

示例:

<?php
preg_match('/(foo)(bar)(baz)/', 'foobarbaz', $matches);// 分成3组,所以$matches数组中的第1,2,3个元素都会有值
print_r($matches);
preg_match('/(foo)(bar)(baz)/', 'foobarbaz', $matches, PREG_OFFSET_CAPTURE); // $matches数组的每个元素都变成数组,增加了偏移量信息
print_r($matches);
?>

结果:
Array
(
    [0] => foobarbaz
    [1] => foo
    [2] => bar
    [3] => baz
)
Array
(
    [0] => Array
        (
            [0] => foobarbaz
            [1] => 0
        )

    [1] => Array
        (
            [0] => foo
            [1] => 0
        )

    [2] => Array
        (
            [0] => bar
            [1] => 3
        )

    [3] => Array
        (
            [0] => baz
            [1] => 6
        )

)

2. preg_match_all 全局正则表达式匹配

语法:

int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )

参数:
$pattern:要搜索的模式,字符串形式。
$subject:输入字符串。
$matches:多维数组,作为输出参数输出所有匹配结果, 数组排序通过flags指定。
$flags:可以结合下面标记使用(注意不能同时使用PREG_PATTERN_ORDER和 PREG_SET_ORDER):
PREG_PATTERN_ORDER:默认值。与 preg_match 一样,结果排序为$matches[0]保存完整模式的所有匹配。$matches[1] 保存第一个子组的所有匹配,以此类推。
PREG_SET_ORDER:结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组), $matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组,以此类推。
PREG_OFFSET_CAPTURE:如果这个标记被传递,每个发现的匹配返回时会增加它相对目标字符串的偏移量。 注意这会改变matches中的每一个匹配结果字符串元素,使其 成为一个第0个元素为匹配结果字符串,第1个元素为 匹配结果字符串在subject中的偏移量。

返回值:
返回完整匹配次数(可能是0),或者如果发生错误返回FALSE。

示例:

<?php
preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
    "<b>example: </b><div align=left>this is a test</div>",
    $out, PREG_PATTERN_ORDER);// $out[0] 放匹配结果,$out[1]放第一个子组的匹配,该例中是闭合标签内的字符串。
print_r($out);
?>

输出:
Array
(
    [0] => Array
        (
            [0] => <b>example: </b>
            [1] => <div align=left>this is a test</div>
        )

    [1] => Array
        (
            [0] => example: 
            [1] => this is a test
        )
)

3. preg_replace 正则搜索和替换

语法:

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
搜索subject中匹配pattern的部分, 以replacement进行替换。

参数:
$pattern:要搜索的模式。字符串或字符串数组。
$replacement:用于替换的字符串或字符串数组。如果这个参数是一个字符串,并且pattern 是一个数组,那么所有的模式都使用这个字符串进行替换。如果pattern和replacement 都是数组,每个pattern使用replacement中对应的 元素进行替换。如果replacement中的元素比pattern中的少, 多出来的pattern使用空字符串进行替换。
replacement中可以包含后向引用\\n 或$n,语法上首选后者。 每个 这样的引用将被匹配到的第n个捕获子组捕获到的文本替换。 n 可以是0-99,\\0$0代表完整的模式匹配文本。 捕获子组的序号计数方式为:代表捕获子组的左括号从左到右, 从1开始数。如果要在replacement 中使用反斜线,必须使用4个("\\\\",译注:因为这首先是php的字符串,经过转义后,是两个,再经过 正则表达式引擎后才被认为是一个原文反斜线)。
当在替换模式下工作并且后向引用后面紧跟着需要是另外一个数字(比如:在一个匹配模式后紧接着增加一个原文数字), 不能使用\\1这样的语法来描述后向引用。比如, \\11将会使preg_replace() 不能理解你希望的是一个\\1后向引用紧跟一个原文1,还是 一个\\11后向引用后面不跟任何东西。 这种情况下解决方案是使用${1}1。 这创建了一个独立的$1后向引用, 一个独立的原文1。
当使用被弃用的 e 修饰符时, 这个函数会转义一些字符(即:'、"、 \ 和 NULL) 然后进行后向引用替换。当这些完成后请确保后向引用解析完后没有单引号或 双引号引起的语法错误(比如: 'strlen(\'$1\')+strlen("$2")')。确保符合PHP的 字符串语法,并且符合eval语法。因为在完成替换后, 引擎会将结果字符串作为php代码使用eval方式进行评估并将返回值作为最终参与替换的字符串。

$subject:要进行搜索和替换的字符串或字符串数组。如果subject是一个数组,搜索和替换回在subject 的每一个元素上进行, 并且返回值也会是一个数组。
$limit:每个模式在每个subject上进行替换的最大次数。默认是 -1(无限)。
$count:如果指定,将会被填充为完成的替换次数。

返回值:
如果subject是一个数组, preg_replace()返回一个数组, 其他情况下返回一个字符串。
如果匹配被查找到,替换后的subject被返回,其他情况下返回没有改变的 subject。如果发生错误,返回 NULL 。

示例:

<?php
$string = 'April 15, 2003';
$pattern = '/(\w+) (\d+), (\d+)/i';
$replacement = '${1}1,$3';
echo preg_replace($pattern, $replacement, $string);
?>

输出:
April1,2003

3. JavaScript 的正则表达式

RegExp 对象参考

1. RegExp 对象

RegExp 对象,是 JavaScript 中的正则对象,描述了字符的模式。

  • 语法:
    var patt=new RegExp(pattern, modifiers);
    var patt=/pattern/modifiers;

  • 参数:
    pattern:模式描述了一个表达式模型。
    modifiers:描述了检索是否是全局,区分大小写等。

  • 示例:
    var re = new RegExp("\\w+");
    var re = /\w+/;

2. RegExp 对象的修饰符

修饰符用于执行区分大小写和全局匹配:

修饰符描述
i执行对大小写不敏感的匹配。
g执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m执行多行匹配。

3. RegExp 对象的方法

方法描述
compile在脚本执行过程中编译正则表达式,也可用于改变和重新编译正则表达式。
exec检索字符串中的正则表达式的匹配。如果字符串中有匹配的值返回该匹配值,否则返回 null。
test检测一个字符串是否匹配某个模式,如果字符串中有匹配的值返回 true ,否则返回 false。

示例:

var patt1=new RegExp("e");
document.write(patt1.test("The best things in life are free")); // 显示 true

4. 支持正则表达式的 String 对象的方法

方法描述语法参数返回值
search检索与正则表达式相匹配的值string.search(searchvalue)正则表达式或字符串Number。与指定查找的字符串或者正则表达式相匹配的 String 对象起始位置。如果没有找到任何匹配的子串,则返回 -1。
match找到一个或多个正则表达式的匹配string.match(regexp)正则表达式Array。数组内容依赖于 regexp 是否具有全局标志 g。如果没有找到任何匹配的文本, 返回 null。否则,将返回一个数组,其中存放了与它找到的匹配文本有关的信息。
replace替换与正则表达式匹配的子串,不会改变原始字符串。string.replace(searchvalue,newvalue)searchvalue是子字符串或要替换的模式的 RegExp 对象。String。新字符串,是用 newvalue 替换了 regexp 的第一次匹配或所有匹配之后得到的。
split把字符串分割为字符串数组,不会改变原始字符串。string.split(separator,limit)separator是字符串或正则表达式。limit可选,指定返回的数组的最大长度。Array,字符串数组。

示例:

var str = "How are you?";
var s1 = str.split(""); //用空字符串分割字符串为数组,得到数组 H,o,w, ,a,r,e, ,y,o,u,?
var s2 = str.split(" ",1); //用空格分割字符串为数组且只留一个元素,得到数组 How
var r = str.replace(/you/g,"me"); //把 you 替换为 me
var s3 = str.search("are"); //返回 are 第一次出现的位置 4
var s3 = str.search("hhh"); //返回 -1
var m = str.match(/how/gi); //全局查找 how,不区分大小写。返回数组 How
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值