java 元字符_正则表达式教程一 —— 特殊字符(元字符)

概述:

正则表达式,又称规则表达式。是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。

正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

它最初是科学家对人类神经系统工作原理的早期研究(一种用数学方式来描述神经网络的新方法)。

Unix的主要发明人 Ken Thompson 将它运用到了计算搜索算法、编辑器qed、编辑器ed(太古老了),从此被广泛应用

那么它有啥用?

它能帮你在一大堆杂乱无章的内容中,找到符合特定模式的内容

比如,爬取其它网站的内容并提取有用信息;内容关键字审核;特定文本内容整体替换

这一节将介绍一下正则表达式的一些特殊字符和简单用法

在讲这些字符/符号的时候,我会用 php 来举一些例子,基本上所有语言的正则表达式都大同小异,若你使用的是其它语言,也可直接把表达式拿去使用试试

一、特殊字符(元字符)

特殊字符即在正则表达式中有特定含义的内定字符。就好比 java,php 等语言中的关键字

1、$

匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'

例子1$s = 'abcd

efd';

preg_match('#[a-z]+?d$#s',$s,$m);//# # 之间的内容为正则表达式,s为修饰符,# 为php中的边界符号,还有 / 也是边界符

print_r($m);//$m 就是我们匹配到的信息

/*

Array

(

[0] => efd

)

*/

匹配以 d结尾(d$) 的一串字符,前面可以是任意a到z 的小写字母([a-z]+?), 其中 s 为修饰符(后面会讲),就是多行模式(Multiline),

所以匹配到了第二行的 efd(因为[a-z]+?不匹配换行),若要匹配整个换行的字符串,则:#([a-z]|\r\n)+?d$#s

2、( )

标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用

例子2$s = 'abc123def456';

preg_match_all('#(\d+)#',$s,$m);

print_r($m[1]);

/*

Array

(

[0] => 123

[1] => 456

)

*/

匹配并捕获字符串中的所有数字,$m[1] 就是捕获到的内容,关于捕获后的使用,将在下面的 \ 符号介绍

\d 等价于 [0-9],关于 [] 字符集下面会讲,只要知道 \d 是表示匹配一个数字就行了

3、+

匹配前面的子表达式一次或多次

见例子2

4、*

匹配前面的子表达式零次或多次

见例子2

5、.

匹配除换行符 \n之外的任何单字符

例子3$s = <<

test!@#$

TEXT;

preg_match_all('#.#s',$s,$m);

print_r($m);

/*

Array

(

[0] => Array

(

[0] => t

[1] => e

[2] => s

[3] => t

[4] => !

[5] => @

[6] => #

[7] => $

)

)

*/

6、[ ]

标记一个中括号表达式字符集合

请看例子1,[a-z] 就是一个字符集合,可以是任意字符,比如我只要匹配 【abc,.】 这个5个字符——[abc,.]

这里有一个特殊的符号 - ,代表一个范围,常用的有 A-Z(大写的字母A到Z),a-z(小写的字母a到z) ,0-9(数字0到9)

7、?

匹配前面的子表达式零次或一次,或指明一个非贪婪限定符

例子4$s = <<

a1a2abbb

TEXT;

//匹配以a开头后面紧跟一个数字或没有数字(用了 ? )的字符串

preg_match_all('#a\d?#',$s,$m);

print_r($m);

/*

Array

(

[0] => Array

(

[0] => a1

[1] => a2

[2] => a

)

)

*/

8、\

将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。

比如匹配在正则中有特殊含义的字符,如 . 、 \ 、 $ 、 ( 、 [ 等等,这里就讲一下 向后引用(反向引用)

例子5$s = <<

this is bthis is i

TEXT;

preg_match_all('#(.+?)\1>#i',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => this is b

[1] => this is i

)

[1] => Array

(

[0] => b

[1] => i

)

[2] => Array

(

[0] => this is b

[1] => this is i

)

)

*/

我想匹配标签 b 和 i (或者其它标签)中的内容,总不能为了每一个标签都写一个表达式吧,比如这个:#(.+?)|(.+?)#i;那么多标签不得写死啊

而标签开头和结尾都是一样的,那么把匹配到的开始标签引用到结束位置不就行了?!

还记得例子2中 () 的作用吗,捕获匹配到的内容,供后面使用。而 \1 就是使用第一个 ( 开始所匹配到并被捕获的内容。在这个例子里 \1 就是匹配到的 b 或 i

那么想一想,若是在 () 中还有 (),如何使用反向引用?

好吧,不用你们想了,我来公布答案。

不管表达式中有多少个 (),都是以 ( 为顺序(从1开始),放在捕获的区域以供后面使用,最多好像是支持 99 个,没试过

在正则表达式中使用之前匹配并捕获(反向引用)的内容就是用 \1 \2 \3 ....各语言可能不同,比如 js 是 $1 ,java 是 \\1

例子6$s = <<

this is b
this is span

this is i

TEXT;

preg_match_all('#(.+?)\2>\1>#i',$s,$m);

print_r($m);

/*

Array

(

[0] => Array

(

[0] => 

this is b

[1] => this is i

)

[1] => Array

(

[0] => div

[1] => span

)

[2] => Array

(

[0] => b

[1] => i

)

[3] => Array

(

[0] => this is b

[1] => this is i

)

)

*/

匹配外层是多字符标签(div span 等)包裹,内层紧跟一个字符的标签(b i 等),因为 ([a-z]) 后面没有跟 + ,说明是匹配一个字符

由于

this is span
不满足内层一个字符的标签,所以没有被匹配

例子7 java 版import java.util.regex.*;

public class Test {

public static void main(String[] args) throws Exception {

String str = "

this is b
this is span
this is i";

Matcher m = Pattern.compile("(.+?)\\2>\\1>").matcher(str);

while(m.find()){

System.out.println(m.group()+"\n"+m.group(1)+"\n"+m.group(2)+"\n开始位置 : "+m.start()+" \n结束位置 : "+m.end()+"\n\n");

}

}

}

输出

this is b

div

b

开始位置 : 0

结束位置 : 27

this is i

span

i

开始位置 : 63

结束位置 : 92

9、^

匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合

例子8$s = <<

1abc

TEXT;

//2def

//ght

//34xyz

preg_match_all('#^\d[^\d]+#',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => 1abc

)

)

*/

匹配以一个数字开头后面紧跟非数字的字符串,这个例子就把 ^ 的两个概念都讲了,例子的结果就是能匹配 1abc,2def,不能匹配 ght,34xyz

这里讲讲为什么不能匹配 34xyz,因为 3 被 \d 匹配了,而 4 就只能被 [^\d]+ 匹配,但是这个集合只匹配非数字字符串,所以不满足要求,整个字符串都不能被匹配

在一个字符集中用 ^ (一定要在字符集的开始位置),如 [^abc] ,那么就表示,不匹配abc这三个字母

10、{ }

标记限定符表达式的开始

这个将在限定符一节中将,简单来说就是表示一个范围

11、|

指明两项(多项)之间的一个选择

例子9$s = <<

this is bthis is ithis is span

TEXT;

preg_match_all('#(.+?)\1>#',$s,$m);

print_r($m);

/*

Array

(

[0] => Array

(

[0] => this is b

[1] => this is i

)

[1] => Array

(

[0] => b

[1] => i

)

[2] => Array

(

[0] => this is b

[1] => this is i

)

)

*/

匹配 b 或者 i 标签包裹的内容,若也要匹配 span, 加上即可,#(.+?)\1>#

特殊字符暂时就介绍这些,单个的字符都很好理解,但想写出复杂的正则表达式却无从下手。

那么如何构造复杂的表达式?

简单来说就是化整为零,正则表达式可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些符号的任意组合。

用多种元字符(特殊字符)与操作符将小的表达式结合在一起来创建更复杂的表达式。

比如 例子5 就用了很多元字符

一定要多练,才能把所有符号牢记于心,都是熟能生巧。

布置一个练习题

待匹配内容

123abc,

456def

a1b2c3

请匹配出 456def

分析下:

1、外面包裹的标签不一定是这几个(div span m)

2、内容是以 数字开头的,后面跟个几个字母

很简单,看上面的几个例子,动动手就可以完成

下一节讲 限定符和符号的运算优先级

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值