你知道应该如何学会正则表达式吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你知道应该如何学会正则表达式吗?相关的知识,希望对你有一定的参考价值。

所有正则表达式的需求,都应该经过自己思考完成. 你每次『ctrl+c ctrl+v』其实都丢失了一次独立思考的机会,即便你事后已经思考了为什么这个正则行得通。我完全反对,上面任何关于正则表达在几小时内就能掌握的论调,虽然我在学校时也是从一个类似30Minute掌握正则表达式的教程开始的。这东西一定要持续的用,才能形成稳定的记忆,毕竟正则这个东西根本不是设计用来给人阅读的。工具,其实没那么麻烦了,Sublime Text 或 类似编辑器的 『ctrl + F』 足矣,平时开发顺带练了。记得打开左下的正则开关,其实大部分涉及到字符串模式匹配的都可以用正则解决,我大概罗列下自己的经历,入门: 解决各个业务上的问题,比如邮箱、手机号等等,开始知道正则能解决什么问题,以及正则的受限性。进阶: 比如在最初写GitHub - leeluolee/puer: more than a live-reload server, built for efficient front-end development的时候,尝试实现一个简化的router。在这个过程中,开始会使用子匹配和特定的宿主语言API实现一些高级特性类express的route 会支持括号内引入子规则 ,比如 /api/blogs/:id(\\d+) ,这里会有一些较复杂递归的处理,配合String.prototype.replace(首参数支持正则)可以较好的解决。在这个阶段,基本我已经可以感觉已经无需查阅任何关于正则的资料,可以自行解决不太复杂的文本模式匹配问题,初步形成了记忆。再进阶: 碰到更复杂的正则表达式的需求 我尝试了使用javascript生成正则表达式,比如在GitHub -leeluolee/nes: a small js selector lib with incredible extensibility, but still very fast 拼装了一个下面的正则,这个几乎是无法人肉维护了,必须用代码生成。

参考技术A

把正则表达式必备网站RegExr: Learn, Build, & Test RegEx加入书签栏,这个网站非常强大,主要的功能有:公式上的悬浮气泡UI解释该规则匹配的字符串。匹配结果也有对应的解释,右侧边栏有正则表达式的详细规范及图中的小抄,再配合刷几道HackerRank上正则表达式的题Programming Problems and Competitions :: HackerRank。这样最多几个小时,正则表达式的基本使用就没问题了。工作中遇到的正则表达式问题基本上都可以用RegExr网站帮助解决。复杂的字符串搜寻、替换工作,无法用简单的方式(类似借助标准库函数)达成。能够帮助你进行各种字符串验证。不止应用于编程语言中:JavaScript、JAVA、Perl、php、C#...也应用于许多操作系统的主流指令中:Linux/Unix、Mac、Windows PowerScript在我们常用的开发工具中,如Fiddler Willow、WebStorm、Vim,正则表达式也能帮助我们方便的进行Find&Replace的工作。

参考技术B

大学,在学校团队里,做一个网站,叫做海投网(海投网 - 大学生求职搜索引擎),每天对着各种奇形怪状的网页源码,写正则,提取招聘信息,然后做聚合,整整做了一个学期,当时遇到了各种奇葩的页面结构,每次为了一个正则都要绞尽脑汁大半天。正则能力不是看出来的,也不是学出来的,真的是一次又一次遇到头疼的问题,动手写出来的。我经常练习正则,比如遍历时做文件匹配,过滤 `.js` 文件但保留 `.min.js` 文件,通常就会打开 Chrome 浏览器,在控制台写起来;比如处理文件格式,将 less 文件转换为 css 文件,会尝试使用正则将层叠括号去掉,将 less 文件扁平化;再比如使用正则动手写一个 js 文件的语法高亮,写一个 ToDone 的语法高亮等等。

20分钟学会正则表达式

程序员的世界有个笑话,在你遇到困难并决定使用正则表达式的时候,你会发现你又多了个困难。正则表达式是个非常强大的工具,老练的程序员常把它当作最后的杀手锏,一旦使用,必会技惊四座。


正则表达式是一种专门用于定义文本的模式匹配规则的语言(英文称作Regular Expressions,现在计算机界更正规的术语是regex-es)。正则表达式有自己的语法和语法规则,初学者使用起来极易出错,但它的价值使你不能不学。以下是个精简版的教程:

20分钟学会正则表达式

1、匹配单个字符

所有的编程语言都有自己的一套定义和使用正则表达式的方法,尽管各有不同,但本文所列的部分几乎适用于所有场合。这些例子使用JavaScript编写,可在浏览器中运行。


最基本的正则表达式是匹配单个字符,规则如下:

  • 点(.)匹配任何字符,如果想要匹配(.),需要用到转义字符(\)

  • 问号(?)表示其前面的字符是可选的,如果想要匹配(?),同样需要用到转义字符(\)


示例:


var text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu.';

/*
 *将会匹配"elit"和"elat",点可匹配任何字符
 *修饰符"g"表示全局模式,即模式将会被应用于所有的字符串,而
 *不是在发现第一个匹配项时立即停止。
 *如果去掉g,改为(var regex = /el.t/;),则只会匹配"elit"。
 */

var regex = /el.t/g;
console.log( text.match(regex) );


/*
 *将会匹配"est"和"lest"
 *问号使得"l"是可选的
 */

var regex2 = /l?est/g;
console.log( text.match(regex2) );

程序的运行结果为:

[“elit”,”elat”] 
[“lest”,”est”]

20分钟学会正则表达式

2、匹配一组字符

基于前面的示例,我们还可以使用集合来匹配一组特定字符:

  • 集合是置于中括号内的一个或多个字符,比如[abc],它将仅匹配其中的一个字符,此例中只会匹配a或b或c。也可以使用^来否定一组字符,例如[^abc]将会匹配除abc外的任何字符。也可以指定集合的范围,例如[0-9]、[a-z],将会匹配该范围内的所有字符。

  • 正则表达式拥有一些内置集合,来帮助我们快速书写正则表达式。例如[0-9]可以写作 \d ,[^0-9]可以写作 \D。还有一些用于单词字符的集合,例如:匹配a到z及数字和下划线—— \w 和 \W(与\d、\D类似,大写表示“非”);匹配空格包括制表符和换行符——\s 和 \S。


看如下示例:


var text = 'cat car can';

//匹配"cat" 和 "can"
console.log( text.match(/ca[tn]/g) );

//匹配"car",注意^
console.log( text.match(/ca[^tn]/g) );


//这个示例演示匹配数字
text = 'I would like 8 cups of coffee, please.';

//匹配text中的数字,此处为8
console.log('How many cups: ' + text.match( /[0-9]/g ));

//更精简的写法是使用  \d
console.log('How many cups: ' + text.match( /\d/g ));

//匹配除数字外的所有字符,将返回一个非数字数组
console.log( text.match(/\D/g) );

程序运行结果如下:

["cat","can"]

["car"]

How many cups: 8

How many cups: 8

["I"," ","w","o","u","l","d"," ","l","i","k","e"," "," ","c","u","p","s"," ","o","f"," ","c","o","f","f","e","e",","," ","p","l","e","a","s","e","."]

20分钟学会正则表达式

3、匹配单词

大多数时候,我们需要匹配整个单词,而不是单个字符,可通过如下的修饰符来完成的这项匹配,这些修饰符用来重复匹配一个字符或字符集:

  • +,匹配前面的字符或字符集一次或多次;

  • *,匹配前面的字符或字符集0次或多次;

  • {x},表示匹配前面的字符或字符集x次,{x,}表示至少匹配x次,{x, y}表示匹配x-y次;


\b模式比较特殊,用于匹配单词边界,也就是指单词和空格间的位置。例如,“\bh”可以匹配“one hour”中的“h”,但不能匹配“match”中的“h”。


看如下示例:


var text = 'Hello people of 1974. I come from the future. In 2020 we have laser guns, hover boards and live on the moon!';

//匹配句中的年份,\d+可匹配一个或多个数字
var yearRegex = /\d+/g;
console.log('Years: ', text.match( yearRegex ) );

//匹配所有以大写字母开头,句号或感叹号结尾的句子
/*
 *问号表示匹配模式是非贪婪的
 *非贪婪模式尽可能少的匹配所搜索的字符串
 *默认的贪婪模式则尽可能多的匹配所搜索的字符串
 *若此处去掉?,则匹配结果是整个text
 */

var sentenceRegex = /[A-Z].+?(\.|!)/g;
console.log('Sentences: ', text.match(sentenceRegex) );

//找到所有以h开头的单词,i修饰符表示不区分大小写
//g修饰符前面已经提过
/*
 * \b 匹配单词边界
 * 若去掉则单词the中的he也会被匹配到
 */

var hWords = /\bh\w+/ig;
console.log('H Words: ', text.match(hWords) );

//找出所有长度为4-6的单词
var findWords = /\b\w{4,6}\b/g;
console.log( 'Words between 4 and 6 chars: ', text.match(findWords) );

//找出所有长度大于5的单词
console.log( 'Words 5 chars or longer: ', text.match(/\b\w{5,}\b/g) );

//找出所有长度为6的单词
console.log( 'Words exactly 6 chars long: ', text.match(/\b\w{6}\b/g) );

程序运行结果如下:

Years: ["1974","2020"]

Sentences: ["Hello people of 1974.","I come from the future.","In 2020 we have laser guns, hover boards and live on the moon!"]

H Words: ["Hello","have","hover"]

Words between 4 and 6 chars: ["Hello","people","1974","come","from","future","2020","have","laser","guns","hover","boards","live","moon"]

Words 5 chars or longer: ["Hello","people","future","laser","hover","boards"]

Words exactly 6 chars long: ["people","future","boards"]

20分钟学会正则表达式

4、匹配/校验整行

在JavaScript中,这种模式会被呗用来验证用户输入的文本字段。除了使用^开头(行开头),结尾(行结尾),其他与一般正则表达式没有什么区别。开头结尾将保证模式跨越整个文本长度,而不只是匹配其中的一部分。


此外,这种情况下我们可以使用正则对象的test()方法来测试字符串是否匹配,匹配则返回true,否则返回false。


看如下示例:


//下面是一组字符串,我们来提取出其中的URL
var strings = [
    'http://tutorialzine.com/posts/',
    'this is not a URL',
    'https://google.com/',
    '123461',
    'http://tutorialzine.com/?search=jquery',
    'http://not a valid url',
    'abc http://invalid.url/'
];

//下面这个简单的正则表达式即可完成这项工作
//^开头$结尾表示整个字符串必须都匹配,而不是只有一部分能匹配
var regex = /^https?:\/\/[\w\/?.&-=]+$/;

var urls = [];
forvar i = 0; i < strings.length; i++ ){
    if( regex.test(strings[i]) ){       
        urls.push(strings[i]);
    }
}

console.log('Valid URLs: ', urls);

程序运行结果如下:

Valid URLs:[“http://tutorialzine.com/posts/“,”https://google.com/“,”http://tutorialzine.com/?search=jquery“]

20分钟学会正则表达式

5、查找和替换

正则表达式另一个常见的应用场景是文本的查找和替换,注意两个基本概念:

  • 组(group):一组置于小括号()中的模式,每个组将捕获并保存与其中模式匹配的文本,这些文本可以通过索引进行访问,从1开始,1表示第一组。

  • 反向引用:在表达式中也可以反向引用组——反斜杠后跟组索引,从\1开始,只有捕获了文本后,\x中的内容才能确定。见下面的示例,这个功能很少使用,你可以忽略它。


看如下示例:


// 使用反向引用,
// 找出仅由相同字母组成的单词
var text = 'Abc ddefg, hijk lllll mnopqr ssss. Tuv wxyyy z.';
var sameLetterRegex = /\b(\w)\1*\b/g;
console.log( text.match(sameLetterRegex) );

//将"John Smith" 替换为"Smith, John"
//每个组(\w+)匹配一个单词
//可通过索引$访问
var name = 'John Smith';
var nameRegex = /(\w+) (\w+)/;
console.log( name.replace(nameRegex, '$2, $1') );

//对于更高级的操作,我们需要提供JS回调
//例如下面将姓变为大写
var upcasename = name.replace(nameRegex, function(string, group1, group2){
    return group2.toUpperCase() + ', ' + group1;
});
console.log( upcasename );

程序运行结果如下:

[“lllll”,”ssss”,”z”] 
Smith, John 
SMITH, John

20分钟学会正则表达式

更多资源推荐和深入阅读

如果你读完并掌握了本文中的内容,差不多就可以解决80%正则表达式相关的问题。以下是一些有用的学习资源和工具,可以帮助你更深入地学习:

  • RegexOne互式正则表达式教程——https://regexone.com/

  • Mozilla有关JavaScript正则表达式的文章——https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

  • Regexr可视化正则表达式调试与测试工具——http://regexr.com/

  • regex101另一个优秀的正则表达式测试工具——https://regex101.com/

  • regular-expressions.info上的更多内容和技术细节(需翻墙访问)——http://www.regular-expressions.info/

  • JavaScript的正则表达式仅适用于拉丁字母,若要支持unicode,请参看——http://stackoverflow.com/questions/280712/javascript-unicode-regexes


20分钟学会正则表达式
20分钟学会正则表达式

不关注



就捣蛋


以上是关于你知道应该如何学会正则表达式吗?的主要内容,如果未能解决你的问题,请参考以下文章

5分钟教你学会JavaScript正则表达式

20分钟学会正则表达式

5分钟包你学会正则表达式

5分钟包你学会正则表达式

半小时学会正则表达式(上)

你是如何学会正则表达式