Skip to content

正则表达式

什么是正则表达式?

正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串

验证邮政编码,6位数字

js_regular_post_code.html
<script>
  //使用传统方法
  function check1(s) {
    if (s.length != 6) return false;
    var numbers = "0123456789";
    for (var i = 0; i < 6; i++) {
      var ch = s.substr(i, 1);
      if (numbers.indexOf(ch) == -1) return false;
    }
    return true;
  }

  //使用正则表达式
  function check2(s) {
    return /^\d{6}$/.test(s);
  }
</script>
源代码
front/js/advanced/regular/src/js_regular_post_code.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>rect</title>
</head>

<body>
  <script>
    var code = "123456"
    alert(check1(code));
    alert(check2(code));

    //使用传统方法
    function check1(s) {
      if (s.length != 6) return false;
      var numbers = "0123456789";
      for (var i = 0; i < 6; i++) {
        var ch = s.substr(i, 1);
        if (numbers.indexOf(ch) == -1) return false;
      }
      return true;
    }

    //使用正则表达式
    function check2(s) {
      return /^\d{6}$/.test(s);
    }
  </script>
</body>

</html>
/^\d{6}$/.test(s)
  • /^\d{6}$/ 是一个正则表达式对象

  • test() 是正则表达式对象的方法,用来检查字符串是否匹配正则表达式对象所描述的模式

  • 也可以写为:var regex = /^\d{6}$/; regex.test(s);

  • 正则表达式由“/”开始和结束

  • ^\d{6}$ 是正则表达式内容,用来描述字符串模式

  • ^ 匹配字符串开头位置

  • $ 匹配字符串结束位置

  • \d 匹配0~9的任意数字

  • {n} 匹配前面的表达式n次

  • ^\d{6}$ 描述的模式为:字符串从开始到结束包含6个数字


正则表达式可以做什么?

检查字符串是否与指定模式匹配(对用户在表单中输入的数据进行校验)

根据指定的模式在字符串中提取子串

替换字符串中符合指定模式的部分

除了JavaScript,其他几乎所有编程语言都支持正则表达式,它还可以在许多其他软件环境中使用,例如文本编辑器、Unix Shell脚本……


正则表达式语法

  • a|b 匹配表达式a或者b,例如/Hello (World|Kitty)!/ 可以匹配"Hello World!"或"Hello Kitty!"

  • [abc] 匹配方括号中的任意字符,例如/[drz]oom/可以匹配"doom"、"room"或"zoom"

  • [^abc] 匹配不在方括号中的任意字符

  • [0-9] 匹配任意从0到9的数字,例如 /No[3-6]/ 可以匹配"No3"、"No4"、"No5"、"No6"

  • [a-z] 匹配任意从a到z的小写字母,[A-Z] 匹配任意从A到Z的大写字母。数字、小写、大写字母三种范围可以组合使用,例如 /[7-8c-eF-H]/ 可以匹配字符7、8、c、d、e、F、G、H; /[^0-9a-zA-Z]/ 可以匹配除了数字和字母以外的任意字符。

元字符,拥有特殊含义的字符:

  • . 匹配除了换行符(\n)以外的任何单个字符

  • \d 匹配一个数字字符,等价于 [0-9]

  • \D 匹配一个非数字字符,等价于 [^0-9]

  • \t 匹配一个制表符

  • \n 匹配一个换行符

  • \r 匹配一个回车符

  • 注意:Windows下每行结尾使用\r\n,Unix/Linux下只有\n

  • \s 匹配任何空白字符(空格、换行、回车、制表符……)

  • \S 匹配任何非空白字符

  • \w 匹配单词字符,等价于 [A-Za-z0-9_]

  • \W 匹配非单词字符,等价于 [^A-Za-z0-9_]

*\unnnn 匹配一个unicode字符,nnnn为16进制unicode编码,例如 /[\u4e00-\u9fa5]/ 匹配所有中文字符

  • \xnn 匹配一个ASCII字符,例如 /[\x00-\xff]/ 匹配所有ASCII字符

匹配字符位置:

  • ^ 匹配字符串开头位置,例如 /^h/ 可以匹配"hello"中的"h",但不能匹配"something"中的"h"

  • $ 匹配字符串结束位置,例如 /h$/ 可以匹配"length"中的"h",但不能匹配"something"中的"h"

  • \b 匹配单词边界,例如 /or\b/ 可以匹配"for you"或者"yes or no"中的"or",但不能匹配"orange"中的"or"

  • \B 匹配非单词边界

  • (?=s) 正向预查,匹配表达式s前面的位置,例如 /Windows (?=XP|98)/ 可以匹配"Windows XP"或"Windows 98"中的"Windows",但不能匹配"Windows 7"中的"Windows"

  • (?!s) 负向预查,匹配不在表达式s前面的位置,例如 /Windows (?!XP)/ 可以匹配除了在"XP"前面之外的"Windows"字符串

量词,匹配出现次数:

  • {n} 匹配前面的表达式n次,例如 /[A-Z]{3}/ 匹配任意三个大写字母,如"CPU"、"IBM",但不能匹配"W3C"

  • {n,m} 匹配前面的表达式最少n次,最多m次(n<=m),例如 /\d{6,8}/ 可以匹配"123456","7654321","88888888"

  • {n,} 匹配前面的表达式最少n次,例如 /go{2,}gle/ 可以匹配"google"、"gooogle"、"goooooooooooogle"

  • * 匹配前面的表达式零次或多次,例如 /#\d*/ 可以匹配"#"、"#1"、"#256"、"#28875474932"

  • + 匹配前面的表达式一次或多次,例如 /ah+/ 可以匹配"ah"、"ahh"、"ahhhhhhhhh"

  • ? 匹配前面的表达式零次或一次,例如 /apples?/ 可以匹配"apple"或"apples"

转义字符:\

需要转义的字符:\ / ^ $ * + ? { } [ ] ( ) . |

例如:

  • /^\$\d+\.\d{2}$/ 可以匹配"$123.45"、"$0.25"等

  • /^\*\.(html|js|css)$/ 可以匹配".html"、".js"、"*.css"

  • /^\(\d{3,4}\)\d{8}$/ 可以匹配"(0431)88951212"、"(010)82619957"等

  • /^[_\$A-Za-z][_\$A-Za-z0-9]*$/ 可以匹配"hello"、"$123"、"_user"、"num10"


示例

匹配手机号码:1xxxxxxxxxx

要求:一共11位数字,第一位必须是1,第二位可以是3、5、8。

例如:"13712345678"、"15987654321"、"1868668888"

匹配QQ号码:xxxxxxxx

要求:大于或等于10000的数字

例如:"10001"、"95001209"、"622009331"

匹配浮点数:-xxx.xxxx

要求:前面可以带负号,整数至少1位,小数任意位,可以没有小数位

例如:"3.14159"、"-123.45"、"6789"、"-256"、"0"

匹配带区号和分机号的电话号码格式:(xxxx)xxxxxxxx-xxx

要求:城市区号必须以0开头,共3位或4位,电话号8位,分机号3位,分机号部分可有可无。

例如:"(0431)88951212-152"、"(010)82619957"

匹配国际电话号码格式:+xx xxx xxxx xxxx

要求:由空格分成4个部分,第一部分+号后面接1~4位国际区号,第二部分3-4位地区号不能以0开始,第三部分3-4位,第四部分4位

例如:"+86 431 8895 1212"、"+1 201 123 4567“

匹配IP地址:xxx.xxx.xxx.xxx

要求:由小数点分开的4段,每段都是0~255之间的数字

例如:"10.0.2.15"、"192.168.0.100"、"127.0.0.1"

匹配电子邮件地址:xxxx@xxx.xxx.xx

要求:@前面至少1个字符(可以是数字、字母、下划线、加减号、小数点,加减号和小数点不能在两端),@后面由.分隔成至少2段,每段至少1个字符(可以是数字、字母、下划线、减号、小数点,减号和小数点不能在两端)

例如:"jack@java-fans.com"、"yao_ming@nba.com"、"hacker+123@sina.com.cn"、"admin.user@apple.com"


使用正则表达式进行替换

字符串替换:

var s = "hello world!";
alert(s.replace("o", "x")); //"hellx wxrld!"

正则表达式替换:

1
2
3
4
5
6
var s = "8 apple is $10, 50 banana is $200";
alert(s.replace(/\$\d+/, "free"));
alert(s.replace(/\$\d+/g, "free"));
//g表示全局匹配,i表示忽略大小写,m执行多行匹配
alert(s.replace(/\$(\d+)/g, "¥$1"));
//用小括号获取匹配,用$1...$n使用获取的字符串

使用正则表达式获取匹配

另一个获取匹配的例子:

var s = "姓名:张三,性别:男,年龄:20";
alert(s.replace(/^姓名:(.+),性别:(.+),年龄:(.+)$/, "有一个$3岁的$2人叫$1"));

在匹配时使用获取匹配:

1
2
3
4
5
6
7
8
var s = "The food in Hollywood is good.";
//要求:将连续两个相同的字母替换成"xx"
alert(s.replace(/o{2}/g, "xx"));
//结果:"The fxxd in Hollywxxd is gxxd."
alert(s.replace(/[a-z]{2}/g, "xx"));
//结果:"Txx xxxx xx Hxxxxxxxx xx xxxx."
alert(s.replace(/([a-z])\1/g, "xx"));
//结果:"The fxxd in Hoxxywxxd is gxxd."

练习

1
2
3
4
var s = "小鸡唱歌叽叽叽,小鸭唱歌嘎嘎嘎,小朋友大笑hahaha";
//要求:把重复三次的部分替换成重复两次,并在每次的后面加上波浪线
//结果:"小鸡唱歌叽~叽~,小鸭唱歌嘎~嘎~,小朋友大笑ha~ha~"
alert(s.replace(/(.+)\1\1/g, "$1~$1~"));
1
2
3
4
5
var s = "<h1>静夜思</h1><p>床前明月光</p><p>疑是地上霜</p><p>举头望明月</p><p>低头思故乡</p>";

//要求:去掉HTML标签(可以是任意标签)
//结果:"静夜思床前明月光疑是地上霜举头望明月低头思故乡"
alert(s.replace(/<\/?[a-z1-6]+>/g, ""));
1
2
3
//要求:去掉HTML标签并在每句后面加斜线“/”
//结果:"静夜思/床前明月光/疑是地上霜/举头望明月/低头思故乡/"
alert(s.replace(/<([a-z1-6]+)>(.*?)<\/\1>/g, "$2/"));

跟在量词后面的问号代表按非贪婪模式匹配(缺省都是贪婪模式,即尽可能多的匹配字符)