正则表达式是用来搜索和替换的字符串
匹配多个搜索结果
JavaScript中通过g来实现
let str = "hello my friends, my girls";
let reg = /my/g;
console.log(str.match(reg));
// [ 'my', 'my' ]
忽略大小写
通过i忽略大小写,
let str = "hello My friends, my girls";
let reg = /my/ig;
console.log(str.match(reg));
// [ 'My', 'my' ]·
任意字符
.可以匹配任意单个字符
let str = `
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls `;
let reg = /sales./g;
console.log(str.match(reg));
// [ 'sales1', 'sales2', 'sales3' ]
匹配特殊字符
使用``来转义字符,.表示匹配.本身。
匹配多个字符中的某一个
使用[]来定义一个字符集合,必须匹配其中的某个成员(并非是全部)
// 不要匹配ca1.xls
let str = `
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
`;
let reg = /[sn]a../g;
console.log(str.match(reg));
[ 'na1.', 'na2.', 'sa1.' ]
匹配一组字符
例如[0123456789]可以使用连字符-这个元字符来定义字符区间
// 不要匹配sam.xls
let str = `
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
`;
let reg = /[sn]a[0-9]./g;
console.log(str.match(reg));
还有例如a-z``A-Z``a-f``A-F
-连字符只能在[]中使用,在其它地方使用只是普通的-
let str = `
body {
background-color: #fefbd8;
}
h1 {
background-color: #0000ff;
}
div {
background-color: #d0f4e6;
}
span {
background-color: #f08970;
} `;
let reg = /#[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]/g;
console.log(str.match(reg));
排除 [^0-9]
使用^来排除不需要匹配的字符
let str =
`
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
`;
let reg = /[ns]a[^0-9].xls/g;
console.log(str.match(reg));
// [ 'sam.xls' ]
^的效果将作用于给定字符集合里的所有字符或字符区 间,而不是仅限于紧跟在^字符后面的那一个字符或字符区间
匹配空白字符
\r回车符\n换行符\t制表符
这些是空白元字符 .
类元字符
匹配数字(非数字) ( \d )
\d等于[0-9]
\D等于[^0-9]
let str = `
var myArray = new Array();
...
if (myArray[0] == 0) {
...
}
if (myArray[1] == 0) {
...
}
`
console.log(str.match(/myArray[\d]/g))
// [ 'myArray[0]', 'myArray[1]' ]
匹配字母数字下划线 ( \w )
\w匹配任何一个字母数字字符或下划线字符( [a-zA-Z0-9] )
\W任何一个非字母数字或下划线字符( [^a-zA-Z0-9] )
let str = `
11213
A1C2E3
48075
48237
M1B4F2
90046
H1H2H2
`
console.log(str.match(/\w\d\w\d\w\d/g))
//[ 'A1C2E3', 'M1B4F2', 'H1H2H2' ]
匹配空白字符 ( \s )
\s匹配任何一个空白字符( [\f\n\r\t\v] )
\S匹配任何一个非空白字符( [^\f\n\r\t\v] )
重复匹配
匹配一个或多个字符 ( + )
+表示匹配一个或多个字符,至少一个。等价于{1,}
匹配邮件格式support@forta.com
let str = `
Send personal email to ben@forta.com. For questions
about a book use support@forta.com. Feel free to send
unsolicited email to spam@forta.com (wouldn't it be
nice if it were that simple, huh?).
`
console.log(str.match(/\w+@\w+.\w+/g))
[ 'ben@forta.com', 'support@forta.com', 'spam@forta.com' ]
匹配邮件(改进版)
let str = `
Send personal email to ben@forta.com. For questions
about a book use support@forta.com. Feel free to send
unsolicited email to spam@forta.com (wouldn't it be
nice if it were that simple, huh?).
`
console.log(str.match(/\w+@\w+.\w+/g))
// [
'ben@forta.com',
'ben.forta@forta.com.',
'support@forta.com.',
'ben@urgent.forta.com.',
'spam@forta.com'
]
匹配零个或多个字符( * )
*表示匹配零次或多次字符。
let str = `Hello .ben@forta.com is my email address. `
console.log(str.match(/\w+[\w.]*@[\w.]+.\w+/g))
// [ 'ben@forta.com' ]
匹配零个或一个字符 ( ? )
?表示匹配零次或一次字符。等价于{0, 1}
匹配两个http链接
let str = `
The URL is http://www.forta.com/, to connect
securely use https://www.forta.com/ instead.
`
console.log(str.match(/https?://[\w./]+/g))
// [ 'http://www.forta.com/', 'https://www.forta.com/' ]
匹配换行符\n或者\r\n
let str = `
"101","Ben","Forta"
"102","Jim","James"
"103","Roberta","Robertson"
"104","Bob","Bobson"
`
console.log(str.match(/[\r]?\n/g))
// [ '\n', '\n', '\n', '\n', '\n', '\n' ]
匹配重复次数 { 3 }
使用{}重复匹配
匹配RGB颜色
let str = `
body {
background-color: #fefbd8;
}
h1 {
background-color: #0000ff;
}
div {
background-color: #d0f4e6;
}
span {
background-color: #f08970;
}
`
console.log(str.match(/#[a-zA-Z0-9]{6}/g))
// [ '#fefbd8', '#0000ff', '#d0f4e6', '#f08970' ]
匹配重复区间范围
可以使用{2, 4}表示最少匹配2次,最多匹配4次
let str = `
4/8/17
10-6-2018
2/2/2
01-01-01
`
console.log(str.match(/\d{1,2}[-/]\d{1,2}[-/]\d{2,4}/g))
// [ '4/8/17', '10-6-2018', '01-01-01' ]
匹配至少重复多少次 {1, }
{3, }表示最少要匹配3次
匹配价格大于100的订单
let str = `
1001: $496.80
1002: $1290.69
1003: $26.43
1004: $613.42
1005: $7.61
1006: $414.90
1007: $25.00
`
console.log(str.match(/\d+: $\d{3,}.\d+/g))
// [ '1001: $496.80', '1002: $1290.69', '1004: $613.42', '1006: $414.90' ]
防止过度匹配(+? *?)
+*都是“贪婪型”元字符,其匹配行为是多多益善,它们会尽可能从开头一直匹配到结尾,而不是碰到第一个匹配时就停止。在不需要“贪婪行为”时,变成“懒惰型”,在后面加一个?,例如+?``*?
let str = `
This offer is not available to customers
living in <b>AK</b> and <b>HI</b>.
`
console.log(str.match(/<[Bb]>.*</[Bb]/g))
console.log(str.match(/<[Bb]>.*?</[Bb]/g))
//[ '<b>AK</b> and <b>HI</b' ]
//[ '<b>AK</b', '<b>HI</b' ]
位置匹配
单词边界(\b)
\b匹配一个单词的开头或结尾
一边是单词(能被\w匹配的字母数字和下划线)
一边是其它内容(能被\W匹配的字符)
let str = `
The cat scattered his food all over the room.
`
console.log(str.match(/\bcat\b/g))
// ["cat"]
\B表示不匹配单词边界,两边都有多余空格的连字符
let str = `
Please enter the nine-digit id as it
appears on your color - coded pass-key
`
console.log(str.match(/\B-\B/g))
// ["-"]
字符串边界(^$)
^表示字符串开头,$表示字符串结尾
多行模式 (m)
多行模式迫使正则表达式引擎将换行符视为字符串分隔符
^既可以匹配字符串开头,也可以匹配换行符之后的起始位置(新行);
$不 仅能匹配字符串结尾,还能匹配换行符之后的结束位置。
m表示多行模式
let str = `
<script>
function doSpellCheck(form, field) {
// Make sure not empty
if (field.value == '') {
return false;
}
// Init
var windowName='spellWindow';
var spellCheckURL='spell.cfm?formname=comment&fieldname='+
field.name;
...
// Done
return false;
}
</script>
`
console.log(str.match(/^\s*//.*$/mg))
// [ ' // Make sure not empty', ' // Init', ' // Done' ]
子表达式 ($nbsp;){2}
例如匹配连续空格 {2}只能匹配到连续出现2次或以上;的情况。
使用()包裹则可以视为子表达式
let str = `
Hello, my name is Ben Forta, and I am
the author of multiple books on SQL (including
MySQL, Oracle PL/SQL, and SQL Server T-SQL),
Regular Expressions, and other subjects.
`
console.log(str.match(/( ){2}/g))
匹配IP地址
let str = `
Pinging hog.forta.com [12.159.46.200]
with 32 bytes of data:
`
console.log(str.match(/(\d{1,3}.){3}\d{1,3}/g))
// [ '12.159.46.200' ]
子表达式嵌套((25[0-5]) | [2[0-4]])
例如匹配适合规则的IP地址,如果使用(\d{1,3}){3}\d{1,3},则可以匹配出500.500.500.500这样错误的IP地址。
利用嵌套规避这种情况
let str = `
Pinging hog.forta.com [12.159.46.200]
with 32 bytes of data:
`
console.log(str.match(/(((\d{1,2})|(1\d{1,2})|(2[0-4]\d)|(25[0-5])).){3}((\d{1,2})|(1\d{1,2})|(2[0-4]\d)|(25[0-5]))/g))
任意的 1 位或 2 位数字。
任意的以 1 开头的 3 位数字。
任意的以 2 开头、第二位数字在 0 到 4 之间的 3 位数字。
任意的以 25 开头、第三位数字在 0 到 5 之间的 3 位数字。
反向匹配( \1 $1 )
\1表示重复匹配第一个子表达式.
$1在替换时使用
匹配两个重复的词
let str = `
This is a block of of text,
several words here are are
repeated, and and they
should not be.
`
console.log(str.match(/[ ]+(\w+)[ ]+\1/g))
// [ ' of of', ' are are', ' and and' ]
匹配标签,防止错误标签<h2></h3>
let str = `
<body>
<h1>Welcome to my Homepage</h1>
Content is divided into two sections:<br/>
<h2>SQL</h2>
Information about SQL.
<h2>RegEx</h2>
Information about Regular Expressions.
<h2>This is not valid HTML</h3>
</body>
`
console.log(str.match(/<[Hh]([0-6])>.*?</[Hh]\1>/g))
// [ '<h1>Welcome to my Homepage</h1>', '<h2>SQL</h2>', '<h2>RegEx</h2>' ]
反向匹配替换
例如Hello, ben@forta.com is my email address.,把b<a href="mailto:$1">$1</a>的$1替换为ben@forta.com
通过exec方法,自动会把匹配到的内容保存到RegExp.$x中,可以直接拿来使用。
let str = `Hello, ben@forta.com is my email address.`;
let r = /(\w+[\w.]*@[\w.]*.\w+)/g;
r.exec(str);
let str2 = `<a href="mailto:$1">$1</a>`
console.log(str2.replace(/$1/g, RegExp.$1));
let str = `
313-555-1234
248-555-9999
810-555-9000`;
let r = /(\d{3})(-)(\d{3})(-)(\d{4})/gm;
r.exec(str);
let str2 = `(${RegExp.$1}) ${RegExp.$3}-${RegExp.$5}`;
console.log(str2);
// (313) 555-1234
环视
向前查看(?=)
向前查看用?=表示,需要匹配=号后面的内容,但是不出现在结果中。
必须放在子表示中 (?=xx)
例如,匹配 协议,不要带上冒号,匹配https:返回https
let str = `
http://www.forta.com/
https://mail.forta.com/
ftp://ftp.forta.com/
`;
let reg = /\w+(?=:)/g;
console.log(str.match(reg));
// [ 'http', 'https', 'ftp' ]
向后查看(?<=)
使用?<=匹配,例如匹配$23.45,返回结果23.45
必须放在子表示中 (?<=xx)
let str = `
ABC01: $23.45
HGG42: $5.31
CFMX1: $899.00
XTC99: $69.96
Total items found: 4
`;
let reg = /(?<=$)[\d.]+/g;
console.log(str.match(reg));
// [ '23.45', '5.31', '899.00', '69.96' ]
否定式向前查看(?!)
肯定式向前查看就是需要匹配这个字符,否定式向前查看就是不要匹配这个字符
匹配数量,不要匹配价格。
let str = `
I paid $30 for 100 apples,
50 oranges, and 60 pears.
I saved $5 on this order.
`;
let reg = /\b(?<!$)\d+\b/g;
console.log(str.match(reg));
// [ '100', '50', '60' ]
正则练习题
1. 金额千分位分割
let str = "12345678";
let reg = /\B(?=(\d{3})+(?!\d))/g;
console.log(
str.replace(reg, (match) => {
return ",";
})
);
\B匹配非单词边界,例如12之间,23之间,匹配一个空字符串。
?=(\d{3})+表示向前查看,后面3位都是数值,后面6位都是数值,后面9位都是数值都可以匹配上...
?!\d表示否定向前查看,第4位不能是数值,第7位不能是数值,第10位不能是数值.....
2. 校验密码强度
密码必须包含大写、小写、数值、特殊字符(!@#$%)
let password = "aB124@72";
let reg = /(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%])[a-zA-z0-9!@#$%]{6,}/g;
console.log(reg.exec(password));
?=.*[a-z],向前查看,表示从字符串开始,任何一个字符后面有a-z的字符,则匹配成功
其它同理
[a-zA-Z0-9!@#$%]{6,}则表示最少匹配这些字符6次