技术标签: php
第一点正则表达式是什么呢?其实他就是一个工具,为了去匹配字符串,从而实现替换功能。
第二点正则表达式千万不要去背,要去理解它。这是关键。
总之 , 我们学习一个系统化的知识,一定要从其基础构成来了解。基础打牢,其他的一切都不是问题一点点抽丝剥茧。
同理 正则亦是如此,再复杂的正则也可以分解成简单正则从而一步一步掌握它所匹配的字符规则。
正则表达式的基本组成元素可以分为:字符和元字符
字符跟代码中的字符其实是一个意思代表一个字母一个数字,元字符比较特殊,他是特殊字符,例如 . * ? + | ,有了这些元字符才能构造出强大的表达式模式
一 一对应即单个字符的映射关系是一对一的,正则表达式被用来筛选匹配的字符只有一个, /a/ 就对应banner中的a,如果想匹配特殊字符的话 就要使用 “\” 它在正则中叫转义字符,例如 /\*/ 来匹配 appe*ll中的星号。其实“\”加上特殊字符 就是让特殊字符在正则中失去它本来的含义只配置这个字符本身而已。
但是如果转义字符“\”加上字符 那么它俩就会有着不同的含义 看下表:
含义 | 正则表达式 | 记忆方式 |
---|---|---|
换行符 | \n | new line |
换页符 | \f | form feed |
回车符 | \r | return |
空白符 | \s | space |
制表符 | \t | tab |
垂直制表符 | \v | vertical tab |
回退符 | [\b] | backspace,之所以使用[]符号是避免和\b重复 |
单个字符是一对一映射的即只能匹配的字符只有一个,这不够呀,只要引入集合和通配符就能实现一对多了。
集合:使用 [ ] 来定义 既然是集合就要匹配这个集合里的一个或者两个元素例如/[123]/ 会匹配1或者2或者3 [1,2,3,4,5]也可以写成[1-5],以此类推 [0-9]就是匹配任意一个字符 [a-z]就是匹配任意一个字母
匹配区间 | 正则表达式 | 记忆方式 |
---|---|---|
除了换行符之外的任何字符 | . | 句号,除了句子结束符 |
单个数字, [0-9] | \d | digit |
除了[0-9] | \D | not digit |
包括下划线在内的单个字符,[A-Za-z0-9_] | \w | word |
非单字字符 | \W | not word |
匹配空白字符,包括空格、制表符、换页符和换行符 | \s | space |
匹配非空白字符 | \S | not space |
一对一和 一对多都说完了 就下来就要说多对多了,其实只要多循环重复正则就行了 那么循环的次数可以分为 0 1 多次 特定次
特定次数是用{min,max} 来表示
0|1 0次或1次 元字符 ? 例如color和colour 同时匹配到就可以使用/colou?r/
>=0 0次或多次 元字符 *
>=1 一次或多次 元字符 +
.*? 代表的是任意尽量少的字符 ?代表的非贪婪模式 一般不会单独用大多是跟一个字母数组链接在一起/.*?a/取a前面任意长度的字符
单词边界 /cat/ 能匹配到cat 和scatted 两种情况 那么久需要加上边界正则表达式 \b /\bcat\b/ 就能匹配到cat单词了
元字符用^来表示字符串的开头 而使用$来表示字符串的末尾
边界和标志 | 正则表达式 | 记忆方式 |
---|---|---|
单词边界 | \b | boundary |
非单词边界 | \B | not boundary |
字符串开头 | ^ | 小头尖尖那么大个 |
字符串结尾 | $ | 终结者,美国科幻电影,美元符$ |
多行模式 | m标志 | multiple of lines / /m |
忽略大小写 | i标志 | ignore case, case-insensitive / /i |
全局模式 | g标志 | global |
字符匹配我们介绍的差不多了。更厉害的要来了,通过嵌套递归和引用本身可以发挥更加强大的功能
从简单到复杂的正则通常要采用分组,回溯引用,逻辑处理的思想 利用这个三种规则可以推演出无限循环的复杂正则
分组:
啥是分组呢:所有以()元字符所包含的正则表达式被分为一组,每一个分组都是一个子表达式,它是构成高级 正则表达式的基础,如果只使用简单匹配语法本质上和不分组是一样的,如果要发挥它的强大的作用 往往要结合回溯引用的方式。
回溯引用:
回溯引用指的是正则表达式后面的部分可以引用前面已经匹配到的字符串。你可以想象成变量,回溯引用的语法想\1,\2
其中\1表示的引用第一个子表达式 \2表示第二个表达式 \0表示整个表达式 \s是匹配到空格
假设现在要在下面这个文本匹配两个连续相同的单词
hello what what world is bealtuf all all shi
利用回溯我就可以很快的写出 /\b(\w+)\s\1/ \s是表示空格\b是单词边界 \w是包括下划线的字符\1就是引用第一个子表达式
回溯引用在替换字符串中十分常用,语法上有些区别,这里来做一下标记 用$1,$2 ...以此类推来引用要被替换的字符串。
preg_replace('/(<img.+src=\"?.+)(images\/)(.+\.(jpg|gif|bmp|bnp|png)\"?.+>)/i',"\${1}uc/images/\${3}",$str);
在匹配规则中要用\1 \2这种形式 而在preg_replace的替换字符中要用$1 $2
下面以js代码做一下演示吧
var str = "abc abc 123";
str.replace(/(ab)c/g,'$1g') g是全局模式
// 得到的结果是 abg abg 123
如果我们不想子表达式被引用 可以使用非捕获正则(?regex)这样就可以避免浪费内存
var str = 'scq000'.
str.replace(/(scq00)(?:0)/, '$1,$2')
// 返回scq00,$2
// 由于使用了非捕获正则,所以第二个引用没有值,这里直接替换为$2
有时我们需要限制回溯引用的使用范围。那么通过前向查找和后向查找就可以达到这个目的
向前查找和向后查找通常是用来匹配文本,其目的是为了确定匹配结果的文本位置(通过指定匹配结果的前后必须是哪些文本)
前向查找是用来限制后缀的凡是以(?=regex)包含的子表达式在匹配的过程中都会用来限制前面的表达式的匹配,例如happy happily这两个词,我想以happ开头的副词那么就可以使用happ(?=ily)来匹配。如果我想过滤所有以happ来头的副词,那么也可以采用负前向查找的正则happ(?!ily),就会匹配到happy单词的happ前缀
介绍完前向查找,接着我们再来介绍一下它的反向操作:后向查找(lookbehind)。后向查找(lookbehind)是通过指定一个子表达式,然后从符合这个子表达式的位置出发开始查找符合规则的字串。举个简单的例子: apple
和people
都包含ple
这个后缀,那么如果我只想找到apple
的ple
,该怎么做呢?我们可以通过限制app
这个前缀,就能唯一确定ple
这个单词了。
/(?<=app)ple/
其中(?<=regex)
的语法就是我们这里要介绍的后向查找。regex
指代的子表达式会作为限制项进行匹配,匹配到这个子表达式后,就会继续向后查找。另外查找不同的是,一种限制匹配是利用(?<!regex)
语法,这里称为负后向查找。与正前向被指定的子表达式不能被匹配到。于是,在上面的例子中,如果想要查找apple
的ple
也可以这么写成/(?<!peo)ple
。
需要注意的,不是每种正则实现都支持后向查找。在javascript中是不支持的,所以如果有用到后向查找的情况,有一个思路是将字符串进行翻转,然后再使用前向查找,作完处理后再翻转回来。看一个简单的例子:
// 比如我想替换apple的ple为ply
var str = 'apple people';
str.split('').reverse().join('').replace(/elp(?=pa)/, 'ylp').split('').reverse().join('');
回溯查找 | 正则 | 记忆方式 |
---|---|---|
引用 | \0,\1,\2 和 $0, $1, $2 | 转义+数字 替换是用$1 $2 $3 |
非捕获组 | (?:) | 引用表达式(()), 本身不被消费(?),引用(:) |
前向查找 | (?=) | 引用子表达式(()),本身不被消费(?), 正向的查找(=) |
前向负查找 | (?!) | 引用子表达式(()),本身不被消费(?), 负向的查找(!) |
后向查找 | (?<=) | 引用子表达式(()),本身不被消费(?), 后向的(<,开口往后),正的查找(=) |
后向负查找 | (?<!) | 引用子表达式(()),本身不被消费(?), 后向的(<,开口往后),负的查找(!) |
*1 PS:ES6标准之前的JavaScript不支持后查找,ES6开始支持
具体示例:
要求用正则取得字符串中圆括号内的子字符串
.如字符串为we@13(HJGY@$)3lp
,返回HJGY@$
.
//正向前查找
foo(?=bar) //匹配后面带有bar的foo 向前去查找找foo
它可以匹配: foobar, abcfoobar fooabcbar中的foo
但是不能匹配:fooabc 中的foo
//正向后查找
(?<=foo)bar //匹配前面有foo的bar
它可以匹配: foobar, 123foobar 中的bar
不可以匹配: 123bar 中的bar
//负向前查找:(?!) 负就是过滤了查找不到
foo(?!bar) //匹配后面不带bar的foo
它可以匹配: foo123
但是不能匹配:foobar
//负向后查找:(?< !)
(?< !foo)bar //匹配前面没有foo的bar
它可以匹配: 123bar 中的bar
不可以匹配: foobar, 123foobar 中的bar
//预查还可以嵌套 :
(?<=(?<!foo)bar)baz
匹配一个baz,它前面要有bar,但是bar的前面不可以是foo
它可以匹配 123barbaz 中的baz
但是不可以匹配foobarbaz
(?<=red)foo red只是条件后向后查找foo ()里面的只是查找的条件正如上面所说的 负就是过滤
var con="coming soon,going gogogo"
var reg = /\b[\w]+(?!=ing\b)/g;//匹配带ing的单词,但是不要ing。注意:如果ing后不加\b,类似于goingabc也会匹配。
console.log(con.match(reg));
//["com", "go"]
文章浏览阅读451次。一、题目在n x n棋盘(有n x n个格点的棋盘)的某个格点上有一个中国象棋马,马走日字。求一条周游棋盘的路径,使得马能够从起始位置起沿着该路径每个格点恰好走一次最后回到出发位置。二、思路1、初期思路: 首先想到的是用DFS来解决,不仅可以遍历全局还可以回溯,于是着手做了起来,虽然是DFS,但是在此题中,不需要用到邻接矩阵,也不需要数组来判断每点是否到过,一..._在n x n棋盘(有n x n个格点的棋盘)的某个格点上有一个中国象棋马,马走日字。求一
文章浏览阅读27次。Android 4.0|-- Makefile|-- bionic (bionic C库)|-- bootable (启动引导相关代码)|-- build (存放系统编译规则及generic等基础开发包配置)|-- cts (Android兼容性测试套件标准)|-- dalvik (dalvik JAVA虚拟机)|-- development (应用程序开发相关)|-- external (and...
文章浏览阅读6.4k次。bin2srec.c/* BIN2SREC - Convert binary to Motorola S-Record file Copyright (C) 1998-2012 Anthony Goffart This program is free software: you can redistribute it and/or modify it under the term_bin文件转s19文件
文章浏览阅读63次。又是一个胡乱涂鸦,最近很长一段时间我就像临产孕妇样,挣扎在“生产”边缘,每次将手放在键盘上,努力憋出一丝一缕。却就是伸不出个头来。还好,我比孕妇自由,可以停下来休息休息。有句话说的好:生活就是在指尖中溜走。忘了是谁说出来的,不过,放在这形容我们IT民工身上再恰当不过。我,就是在屏幕前览尽世间百态,冷暖情怀。在指尖上赢取生活薪水,展望美好未来。不是我颓废,也非自我解嘲。...
文章浏览阅读228次。在本地浏览器上输入www.hello.com时,简单的实现流程是:在客户端上,检查本地的hosts文件中是否有主机名和ip对应,有对应ip,则用HTTP协议封装数据请求,添加应用层首部,添加tcp首部,添加ip首部,添加mac地址后从本地出去,到对应的WEB服务器上,没有对应的ip,则查找resolv.conf文件上DNS的位置,DNS不在同一网络内,则请求需要通过..._location 以某个请求开始
文章浏览阅读82次。C++网络编程离不开socket编程。我们现在使用socket编写简单的回声服务器。流程这里所说的流程包括两部分:socket函数调用流程。服务器与客户端交互流程。socket函数调用流程服务器与客户端交互流程回声服务器主要功能:服务器将接收到来自客户端的数据传回客户端。服务器的功能:服务器在同一时刻只能与一个客..._回声客户端多次调用write会使数据一次性到达服务器
文章浏览阅读197次。ICINGA项目是 由Michael Luebben、HendrikB?cker和JoergLinge等人发起的,他们都是现有的Nagios项目社区委员会的成员,他们承诺,新的开源项 目将完全兼容以前的Nagios应用程序及扩展功能。在新项目的网站上,他们是如此定义ICINGA的,这将是一个介于Nagios社区版和企业版间的产 品。特别将致力于解决Nag...
文章浏览阅读278次。想问这样的问题,其实是自己心中没有个谱,一直用 js 计算性能来衡量 浏览器dom 操作性能。js性能和浏览器性能其实是两码事。这个问题很抽象,它里面涉及挺多个小的知识点。重申一点,js 操作 Dom 很耗性能,其实是在说很耗浏览器性能,具体和 js计算 性能没多大的关系;文章大致行文思路如下:URL从输入到页面展示的过程渲染HTML的过程为什么很“慢”重排重绘优化方案URL从输入到页面展示的过程..._原生jsfor循环动态渲染dom
文章浏览阅读647次。起因:爬取拉勾网职位信息模块的技术栈,实现把技术栈爬回之前的csv文件(以新增列的方式)具体实现过程如下:使用Pandas的read_csv方法读取csv文件里面的PositionId,访问对应的网址设置headers、cookies、time.sleep、try-except,防止反爬机制利用BeautifulSoup方法爬取对应源码并用html.parser实现转化成Html5格式使用正则表达..._python爬虫中一般csv文件自动创建的在那里
文章浏览阅读1.6k次。传统的课堂教学模式往往形成了老师单向灌输、学生被动接受的局面,我们不难看出传统教学模式的缺陷是非常明显的,其中关键的是作为认知主体的学生在整个教学过程中都始终处于被动地接受知识的地位,学生学习的主动性被忽视,甚至被压抑。很显然,这与现代社会对人才培养的要求是不相符合的,这种模式担负不了培养高素质的创造性人才的重担,因此,改变传统教学模式,打造适应新课改要求的高效课堂模式势在必行。这个时候有人就会说..._利用h5协助做课件
文章浏览阅读2.8k次。最近项目中运用到了R读取文件数据,所以把相关好用的、经过验证的方法总结了一下,有效避免下次入坑。1. R读取txt文件使用R读取txt文件直接使用read.table()方法进行读取即可,不需要加载额外的包。read.table("/home/slave/test.txt",header=T,na.strings = c("NA"))1注意,此处的na.strings = c("NA") 的意思是..._r语言输出txt文件
文章浏览阅读213次。义乌机场开通义乌-首尔国际货机航线 义乌提供义乌机场开通义乌-首尔国际货机航线 义乌提供中新网义乌1月22日电 (记者 奚金燕)1月22日早晨7时30分,随着一架载有6吨货物从首尔飞往义乌的货机缓缓驶入机坪,标志着浙江义乌机场货机航线正式开通。地处浙江省中部的义乌,坐拥全球最大的小商品市场,有180万种商品销往全球200个国家和地区。近年来,义乌正致力于“买全球、卖全球”,加快打造世界“小商品之都..._近期坐飞机去义乌要隔离吗?