正则表达式

前言

一直以来都逃避正则,但写代码不会一点正则有时候真的很痛苦,所以还是得学一下最基本的. 这里做一下笔记呗.

 

参考:

正则表达式30分钟入门教程

Github – learn-regex

在线测试

阮一峰 – RegExp对象

 

匹配

\b

如果我们想匹配一个单词. 比如 hi, 那么我们一定不希望它匹配到 his, hit 等等 

那么我们可以加上 \bhi\b 这样就 ok 了. 它的逻辑是匹配的字前后不可以是字母或数字 (符号, 空格都是 ok 的)

 

.

点匹配万物, 除了换行

 

\d

匹配数字, 小数点不匹配哦,不要傻傻的

 

\w

匹配字母,数字, 汉字和下划线, 不要问我为什么跑出一个下划线来...

如果不希望下划线,也可以用另一个写法 [a-zA-Z0-9] 但这个不匹配汉字

 

\s

匹配空格和 tab

 

^ 和 $

通常会一起用, ^ 是表示匹配第一个字符串开始. 比如 ^a 就是说第一个字一定要是 a 

如果只是 a 那么意思是字符串里头只要有 a 就可以了, ^ 就只能是开头就要 a 

$ 就是结尾. 

所以我们验证一整个字符串通常就会用到这个了

 

匹配数量

上面讲了匹配,接下来讲一下要求匹配的数量

*

0次或多次, 比如 aaa 如果我只是写 a 那么会有 3 给 match (每一个 match 里面一个字)

而我写 a* 就只有一个 match 里面有 3 个字

 

+

1次或多次. 和 * 一样, 唯一区别是 * 可以 0 次,这个最少一次

 

?

0次或1次, 就是有或没有. 重点不是数量了, 所以它是没有多次概念的

 

{n}

n 就是任你写一个数字. 要配个几个就几个

 

{n,}

n 个以上, 反过来是没有的哦 {,n} 《--这个是错误的

 

{n,m}

inclusive between n and m 

 

其它

方括号[]

方括号是单个匹配,如[abc]他限制的不是abc连续出现,而是只能是其中一个,这样写那么规则就是找到这个位置时只能是a或是b或是c; 
方括号是正则表达式中最常用的,常用的用法有:[a-zA-Z0-9]匹配所有英文字母和数字,[^a-zA-Z0-9]匹配所有非英文字母和数字。

这段抄来的. 我还没悟道, 之后再写.

里面不是连环的,而是类似单个 or , 比如 [aeiou] 匹配的不是连续而是 a 或 e 或 i 或 o 或 u.

另一个特点是 [.] 匹配的是 . 而不是任意字符, 但是 [\s] 依然是匹配空格. 所以不能理解为里面没有元字符. 再研究

 

|

或者 \d{3} | abc 就是说 3 个数字或者匹配 abc 字符串

 

反义 not

\S  \s 以外

\W \w 以外, 

\D \d 以外

[^aeiou] 加上 ^ 表示以外

[^a-zA-Z0-9_\s] 可以算是匹配符号

 

(\d)

圆括弧是把表达式抱起来用,和数学有点像. 

然后就是这样写 (ab){2}  ab出现 2次, 如果是 ab{2} 那么只是 b 出现 2 次.

(ab|cd) 配合 or 也是经常的用法

 

断言

参考: 正则表达式分组、断言详解

<title>dada</title>

如果想匹配出 dada 而已, 那么就一定要用到断言了. 

断言的功能是它可以写一些匹配,但是最终缺没有被匹配出来 

像上面的表达是这样的

我想找 .* whatever 但是前面必须是 <title> 后面必须是 </title>

4 种断言写法 

(?=X)

(?<=X)

(?!X)

(?<!X)

共同点是 (?)

然后一种是等于(=), 一种是不等于(!)

然后一种有箭头(<), 一种没有. 有箭头的是说断言放在前面. 没有的就放后面

所以上面的写法是 

step 1 : *. 匹配所有

step 2 : (?<=<title>).* 断言在前面所有要箭头

step 3: (?<=<title>).*(?=<\/title>) 断言在后面所以没有箭头

 

Javascript 正则

题目: 找出 href 值

const html = `    <a href="/contact">Contact</a>
    <a href="/about">About</a>`;

答案 /contact 和 /about

创建 regex

const regex = new RegExp('<a .*href="(.*)"', 'img');

第一个参数是 pattern, 它是一个 string, 可以动态拼接哦.

第二个参数 'gim' 分别代表 

global: 是否要匹配多个, 还是只匹配出第一个.

ignoreCase : 匹配不区分大小写

multiline: 当有多行 (\n) 的时候 ^$ 开头结尾是每一行.

如果没有要动态拼接, 也可以用 regex syntax, 下面这句和上面是等价的

const regex = /<a .*href="(.*)"/gim;

查看 regex

console.log(regex.ignoreCase); // true
console.log(regex.multiline); // true
console.log(regex.global); // true
console.log('source', regex.source); // <a .*href="(.*)"

这些都是 readonly 属性哦, 无法修改的. 只能重新做新的

执行查找

console.log(regex.exec(html));
console.log(regex.exec(html));
console.log(regex.exec(html));

结果

两个点要注意:

1. 执行了 3 次, 但是 result 是不同的哦. Regex 内部会记入执行到哪里, 下一次继续, 直到最后匹配不到返回 null, 然后再从头开始.

2. 返回的 array 第一个是完整匹配, 第二个是圆括弧的局部匹配. 如果有多个圆括弧, 那么 array 会有第 3,4,5... 个

Regex.test

console.log(regex.test(html)); // true

它是一个简单的匹配返回 boolean, 匹配到就返回 true, 没有就返回 false.

String.match and String.replace

上面都是用 Regex 去做匹配, 它比较底层, 虽然可以实现所以需求, 但是不过方便.

string.match, replace 则是它的上层封装.

console.log(html.match(regex)); 
console.log(html.replace(regex, 'value=$1'));

结果

两个点要注意:

1. match 无视圆括弧, 它只返回完整匹配到的

2. replace 可以内可以使用 $1 表示第一个圆括弧匹配的值. 它适合用在当想替换所有字但是其中一小部分要保留的时候.

 

C# 正则

var html = @"
    <a href=""/contact"">Contact</a>
    <a href=""/about"">About</a>
";
var regex = new Regex(@"<a .*href=""(.*)""", RegexOptions.IgnoreCase | RegexOptions.Multiline);
var matchCollection = regex.Matches(html);
foreach (var matched in matchCollection.ToArray())
{
    var childMatched = matched.Groups[1].Value;
}

和 JS 大同小异, 我只说说不同的地方.

1. C# 没有 Global, 它是在调用的时候通过 regex.Match 和 regex.Matches (plural 作为 Global) 来表达的, .Replace 则一定是 Global

2. match Collection 结构比较多层, 但是依然可以拿到圆括弧的匹配

replace

var value = regex.Replace(@"<a .*href=""(.*)""", "value=$1");

 

posted @ 2020-04-29 02:18  兴杰  阅读(279)  评论(0编辑  收藏  举报