正则使用总结

前言

在迁移md时,需要将 md 中的图片格式![](xxx.png)<img src=xxxx>转换成附件中新的地址,这样就不得不使用正则来完成,借此机会对Java的正则做一个小的归纳

语法

正则的语法其实挺有意思,从语言的角度看,正则中没有动词、没有形容词,主要由名词与量词组成的一个字符串。名词首先有字符,然后由字符组成字符组,各个字符之间有着一定的逻辑关系,最后由量词来进行限定。

字符

这里的字符主要指的是单字符

字符描述
.任意字符
\sspace空白符(空格、tab、换行、回车)
\S非空白符
\d数字[0-9]
\D非数字
\wword词字符[a-zA-Z0-9]
\W非词字符
^一行的起始
$一行的结束
\b词的边界

对于特殊字符需要用到转义符\

字符组[]

这里指的多个字符组成

字符描述
[abc]包含a或b或c的任意字符,[]取并集,表示或
[^abc]除了a、b、c之外的任意字符,[]中的^否定
[a-zA-Z]从a-z或从A-Z的任意字符
[abc[hij]]包含a | b | c | h | i | j的任意字符
[a-z&&[hij]]h | i | j 的任意字符,&&取交集,表示与

逻辑关系

字符描述
XYY跟着X后
X|Y
[]或,见上
&&与,见上
^非,在[]中表示非
()捕获组,限定这几个是一组,可以用来被引用

group()

我们在进行一个格式的匹配时,往往只需要提取出该格式中的某段字符,比如在这里的md图像格式是,![](),但我只选用()中的图片地址进行替换。这样就用到了group。

分组用()来指明是一组,然后可以通过Matcher.group(i)在指明是哪一组。

来看看分组的i:A(B(C))D

它分成了3组:组0是ABCD、组1是BC、组2是C.

应该是一个队列的方式见到(就放到队列中。

量词

量词表示几个的意思,跟在字符后边

字符描述
X?1个或零个X
X+1个或多个X
X*任意个X
X恰好n个X
X{n,}至少n个X
X{n,m}至少n个,且不超过m个X

对于字符组时,X一般需要用()限定起来

abc+,表示匹配ab,后边跟1个或多个c

(abc)+,表示1个或多个abc序列

其他

  • (?i) 使正则忽略大小写。
  • 在匹配 .{[(?$^* 这些特殊字符时,需要在前面加上 \\,比如匹配 . 时,Java 中要写为 \\.,但对于正则表达式来说就是 \.
  • 在匹配 \ 时,Java 中要写为 \\\\,但对于正则表达式来说就是 \\

String中使用正则

字符串中使用正则有3个函数:

函数描述
s.matches("regex")当正则表达式匹配整个字符串时,返回true
s.split("regex")按匹配的正则表达式切片字符串
s.replaceAll("regex", "replacement")替换所有匹配的字符
s.replaceFirst("regex", "replacement")替换第一个匹配的字符
"-1234".matches("-?\\d+");			// true
"+9111".matches("(-|\\+)?\\d+";  // true
  
   String posts = "Then, when you have found it, you must" +
                "cut down the mighiest tree in the forest...";
    posts.split(" ");	// [Then, , when, you, have, found, it, ,you, must,...] 这样,逗号会被切在内
    posts.split("\\W+"); // [Then, when, you, have, found, it, you, must ...] 这样,逗号等非字符的都会用做切分
    
    posts.replaceFirst("f\\w+", "located");  // 将第一个found替换成located

Pattern、Matcher

这里将正则表达式抽象成了Pattern,将匹配抽象成了Matcher。

Pattern接口比较简单,主要就是compile进行构造。

Pattern p = Pattern.compile("\\w+");

Matcher的接口就比较丰富了,主要包括:

函数说明
Matcher m = p.matcher("posts");由Pattern构造Matcher
m.find()迭代器,判断是否有匹配上的字符串
m.group()获取匹配上的字符串,group(1),可以获取分组
m.start()获取匹配上字符串所在的起始索引
m.end()获取匹配上字符串所在的结束索引
m.split("posts")用m去切分参数
m.replaceAll()/m.replaceFirst()替换
 public static void main(String[] args) {
        String text = "Hello Regex!";

        Pattern pattern = Pattern.compile("\\w+");
        // Java 中忽略大小写,有两种写法:
        // Pattern pattern = Pattern.compile("\\w+", Pattern.CASE_INSENSITIVE);
        // Pattern pattern = Pattern.compile("(?i)\\w+"); // 推荐写法
        Matcher matcher = pattern.matcher(text);
        // 遍例所有匹配的序列
        while (matcher.find()) {
            System.out.print("Start index: " + matcher.start());
            System.out.print(" End index: " + matcher.end() + " ");
            System.out.println(matcher.group());
        }
        // 创建第两个模式,将空格替换为 tab
        Pattern replace = Pattern.compile("\\s+");
        Matcher matcher2 = replace.matcher(text);
        System.out.println(matcher2.replaceAll("\t"));
    }
}

结果:
Start index: 0 End index: 5 Hello
Start index: 6 End index: 11 Regex
Hello    Regex!

参考

# 语言 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×