标签:
之前好一段时间,自己很抵触“正则表达式”。一是,对其了解甚浅,不能很完整的掌握;再者,觉得好多需要正则的,要不网上可以找到,要不可以使用其他方式去实现。总之,对于正则毫无心得。
最近,看完了《JavaScript忍者秘籍》这本书,对正则有了全新的认识,自己也尝试了总结了一些,在开发中,让好多事情变得事半功倍。
正则表达式是一个拆分字符串并查询相关信息的过程。
正则表达式通常被称为一个模式(pattern),是一个用简单方式描述或者匹配一系列符合某个语法规则的字符串。
ECMAScript通过RegExp类型来支持正则表达式。
var expression = /pattern/flags;
var expression = new RegExp("pattern", "flags");
注意:在开发过程中,如果正则是已知的,则优先选择字面量语法;而构造器方式则是用于运行时,通过动态构建字符串来构建正则表达式。
RegExp每个实例都具有下列属性,通过这些属性可以取得有关模式的各种信息。
示例1:
var pattern1 = /\[bc\]at/i;
// 等价于
var pattern1 = new RegExp("\\[bc\\]at", "i");
console.log(pattern1.global); //false
console.log(pattern1.ignoreCase); //true
console.log(pattern1.multiline); //false
console.log(pattern1.lastIndex); //0
console.log(pattern1.source); // \[bc\]at
exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。
返回的数组虽然是Array的实例,但包含两个额外的属性:index和input。
其中index表示匹配项在字符串的位置,而input表示应用正则表达式的字符串。
注意:在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)。
示例1:
var text = "cat, bat, sat, fat";
var pattern1 = /.at/;
var matches = pattern1.exec(text);
console.log(matches.index); // 0
console.log(matches[0]); // cat
console.log(pattern1.lastIndex); // 0
matches = pattern1.exec(text);
console.log(matches.index); // 0
console.log(matches[0]); // cat
console.log(pattern1.lastIndex); // 0
示例2:
var text = "cat, bat, sat, fat";
var pattern2 = /.at/g;
var matches = pattern2.exec(text);
console.log(matches.index); // 0
console.log(matches[0]); // cat
console.log(pattern2.lastIndex); // 3
matches = pattern2.exec(text);
console.log(matches.index); // 5
console.log(matches[0]); // bat
console.log(pattern2.lastIndex); // 8
test()接受一个字符串参数。在模式与该参数匹配的情况下返回true;否则,返回false。
注意:在只想知道目标字符串与某个模式是否匹配,但不需要知道其文本内容的情况下,使用这个方法非常方便。
示例:
var text="000-00-0000";
var pattern=/\d{3}-\d{2}-\d{4}/;
if(pattern.test(text)){
console.log("The pattern was matched.");
}
如果一个字符不是特殊字符或者操作符,则表示该字符必须在表达式中出现。
示例:
var pattern = /test/;
pattern.test("test"); // true
pattern.test("testabc"); // true
注意:要想只允许匹配test,需/^test$/
很多时候,我们不想匹配一个特定的字符,而是想匹配一个有限字符集中的某一个字符。可以通过“[]”来实现。
示例:
var pattern1 = /[abc]/; // “a”、“b“、”c“中的任何一个字符
var pattern2 = /[^abc]/;// 除了“a”、“b“、”c“以外的任何一个字符
var pattern3 = /[a-c]/; // “a”到”c“之间的的任何一个字符(等价于pattern1)
如果我们需要匹配[、$、^、]等特殊字符,在正则中,使用反斜杠可以对任意字符进行转义,让被转义的字符作为本身进行匹配。
示例:
var pattern1 = /\<a\/\>/; // 匹配<a/>
var pattern2 = /\w+@\w+\.\w+/; //简单的邮箱匹配
如果正则表达式第一个字符是“^”,则表示要从字符串的开头进行匹配。如果正则表达式最后一个字符是“$”,则表示必须出现在字符串的结尾。
/^test/; // 只能匹配以“test”开头的字符串
/test$/; // 只能匹配以“test”结尾的字符串
/^L.*G$/; // 只能匹配一“L”开头、“G”结尾的字符串
/a?/; // 零次或一次
/a+/; // 一次或多次
/a*/; // 零次或多次
/a{4}/; // 连续出现四次a
/a{4,7}/; // 连续出现四次到7次
/a{4,}/; // 连续出现四次及以上
补充:
这些重复操作符可以是贪婪的
或非贪婪的
。默认情况下是贪婪的。
在操作符后面加一个问号(?),可以让该表达式变成非贪婪的:进行最小限度的匹配。
示例:
var pattern1 = /a+/;
var pattern2 = /a+?/;
pattern1.exec("aaa"); // ["aaa"] 匹配所有三个字符
pattern2.exec("aaa"); // ["a"] 只匹配一个字符,因为一个a字符就可以满足
使用“()”可以进行分组,当正则表达式有一部分用括号进行分组时,它具有双重责任,同时也创建所谓的捕获。
可以用“|”表示或的关系
示例:
/(lg)+|(ligang)+/; // 匹配出现一次或多次的“lg”或“ligang”
在反斜杠后面加一个要引用的补货数量,该数字从1开始。
示例:
/^([dtn]a\1)/; // dad tat nan
可以任意一个以“d”、“t”、“n”开头,且后面跟着一个“a”字符,最后跟着和第一个捕获相同的字符。
注意:
/[dtn]a[dtn]/; // 可以是 dat dan等
上述二者不同!!!
补充:在匹配XML类型的标签元素很有用!
/<(\w+)>(.+)<\/\1>/; // <a>click me</a>
旧版浏览器声明的透明度规则如下:filter:alpha(opacity=50);
通过正则获取其透明度的值:
var filter = "alpha(opacity=50);";
// opacity= 直到出现“)”
var result = filter.match(/opacity=([^)]+)/);
console.log(result); // ["opacity=50", "50"]
console.log(result[1] / 100); // 0.5
注意:match返回的数组的第一个索引值总是该匹配的完整结果,然后是每个后续捕获结果。
示例1:
var html = "<div class=‘test‘><b>Hello</b></div>";
var result = html.match(/<(\w+)([^>]*?)>/); // ?为非贪婪模式(上述有提及)
console.log(result); // ["<div class=‘test‘>", "div", " class=‘test‘"]
示例2:
var html = "<div class=‘test‘><b>Hello</b></div>";
var result = html.match(/<(\w+)([^>]*?)>/g);
console.log(result); // ["<div class=‘test‘>", "<b>"]
说明:
示例1为非全局匹配,返回结果同上述“获取其透明度的值”,只是其包含了两个捕获。
示例2为全局匹配,返回全局匹配结果,而不是每个匹配的捕获结果。
可以引用捕获到的匹配结果的两种方式:一是,自身匹配;二是,替换字符串。
方式一:上述“反向引用”已提及,/<(\w+)>(.+)<\/\1>/; // <a>click me</a>
方式二:将驼峰变量变为用中划线替换,这在AngularJS等框架中太常见。
如:ngClick –> ng-click
function camelCaseToDash(str){
// $1即为正则中第一个捕获,同上述的“\1”
return str.replace(/([A-Z])/g, "-$1").toLowerCase();
}
camelCaseToDash("ngClick"); // "ng-click"
小括号有双重责任:不仅要进行分组操作,还可以指定捕获。
如果正则表达式中存在大量的分组,就会引起很多不必要的捕获。
在开始括号后面加一个“?:”可以让其不进行捕获。
示例:
var pattern1 = /((ligang-)+)good/;
var pattern2 = /((?:ligang-)+)good/;
// ["ligang-ligang-good", "ligang-ligang-", "ligang-"]
console.log("ligang-liganggood".match(pattern1));
// ["ligang-ligang-good", "ligang-ligang-"]
console.log("ligang-liganggood".match(pattern2));
将正则表达式作为replace()方法的第一个参数时,导致在该模式的匹配元素(全局匹配的话,就是多个匹配元素)上进行替换,而不是在固定字符串上进行替换。
示例:
"ABCligangDEF".replace(/[A-Z]/g, ‘X‘); // "XXXligangXXX"
其最大的特性是可以接受一个函数作为替换值,而不是一个固定的字符串。函数的返回值是即将替换的值。
参数列表:
(1)匹配的完整文本
(2)匹配的捕获,一个捕获对应一个参数
(3)匹配字符在源字符串中的索引
(4)源字符串
示例:将横线替换成驼峰
如:ng-click --> ngClick
function dashToCamelCase(str) {
return str.replace(/-(\w)/g, function(all, letter){
console.log(arguments);
return letter.toUpperCase();
});
}
dashToCamelCase(‘ng-click‘); // arguments --> ["-c", "c", 2, "ng-click"]
由于全局正则在每一次成功匹配的时候都会调用这样的替换函数。这种技术甚至可以超越简单的机械替换,并且可以作为字符串遍历的一种手段。
示例:压缩查询字符串
如:将foo=1&foo=2&blah=3 –> foo=1,2&blah=3
function compress(source) {
var keys = {}; // 存储
source.replace(/([^=&]+)=([^&]*)/g, function(full, key, value){
keys[key] = (keys[key] ? keys[key] + "," : "") + value;
// 我们不关心源字符串发生替换操作,只利用该函数的副作用
return "";
});
var result = [];
for(var key in keys) {
result.push(key + "=" + keys[key]);
}
return result.join("&");
}
compress("foo=1&foo=2&blah=3"); // "foo=1,2&blah=3"
《JavaScript高级程序设计》中提供了“提取URL的搜索字符串中的参数”的方法
如:当前浏览器地址为:http://blog.csdn.net/ligang2585116?a=1&b=2
function urlArgs(){
var args = {};
var query = location.search.substring(1);
var pairs = query.split("&");
for(var i=0; i<pairs.length; i++){
var pos = pairs[i].indexOf(‘=‘);
if(pos == -1) continue;
var name = pairs[i].substring(0,pos);
var value = pairs[i].substring(pos+1);
value = decodeURIComponent(value);
args[name] = value;
}
return args;
}
urlArgs(); // {a: "1", b: "2"}
使用上述方式实现:
function enhanceUrlArgs(query){
var args = {};
query.replace(/([^?&=]+)=([^&])/g, function(full, key, value){
args[key] = value;
return "";
});
return args;
}
enhanceUrlArgs(location.search); // {a: "1", b: "2"}
注意:上述获取搜索字符串参数的方法,都不能存在相同的key,如果有相同的key,需要求参照compress()方法进行处理!!
示例:修建字符串两头多余的空格
function myTrim(str) {
// 以空格开头,后续出现零次或多次
// 以一个或多个空格结尾
return str.replace(/(^\s\s*)/, "").replace(/\s\s*$/, "");
// return str.replace(/(^\s+)/, "").replace(/\s+$/, "");
}
示例:匹配所有字符,包括换行符
var html = "<b>Hello</b>\n<i>world</i>";
console.log(/.*/.exec(html)[0]); // <b>Hello</b>
console.log(/[\s\S]*/.exec(html)[0]); // <b>Hello</b>\n<i>world</i>
console.log(/(?:.|\s)/.exec(html)[0]); // <b>Hello</b>\n<i>world</i>
最佳方案:用于匹配任何不是空白字符的字符,以及匹配任意一个空白字符,联合起来就是匹配所有字符。
示例:匹配Unicode
var text = "\u674e\u521a";
console.log(text.match(/[\w\u0080-\uFFFF_-]+/)); // ["李刚"]
示例:开发人员可能将元素的id值设置为form:update,我们只能通过转义来支持
// 该正则表达式允许匹配一个单词字符,或者一个反斜杠后面跟随任意字符
var pattern = /^((\w+)|(\\.))+$/;
pattern.test("formUpdate"); // true
pattern.test("form\\:update"); // true
支持正则表达式的字符串方法:
标签:
原文地址:http://blog.csdn.net/ligang2585116/article/details/51348024