首页 > 其他分享 >性能篇:String慎重使用正则表达式?

性能篇:String慎重使用正则表达式?

时间:2024-01-03 10:36:48浏览次数:30  
标签:匹配 String NFA 正则表达式 模式 回溯 自动机 慎重


大家好,我是小米,一个热爱技术分享的小伙伴。今天,我们将深入探讨一个在编程中经常用到但却常常被忽视的话题——正则表达式。正则表达式是一个强大的文本匹配工具,然而在使用它时,我们也要注意一些性能上的问题,特别是在处理大量数据时。本文将带你一起深入了解正则表达式的性能优化和一些使用技巧。

什么是正则表达式?

正则表达式是一种用于描述字符串模式的表达式,广泛应用于文本搜索、匹配和替换。通过一些特殊字符和语法规则,我们可以定义一种模式,然后用来匹配输入的文本。

正则表达式引擎

正则表达式引擎根据匹配原理可以分为DFA(Deterministic Finite Automaton)自动机和NFA(Nondeterministic Finite Automaton)自动机。

DFA 是一种确定型有限自动机,它在任何给定的时间点只能处于有限数量的状态之一。而 NFA 是一种非确定型有限自动机,它在某个状态下,有可能有多个状态可以选择。

在实际编程中,常用的正则表达式引擎往往是基于NFA的。

NFA自动机的回溯问题

尽管NFA自动机在理论上更加灵活,但在实际匹配中,NFA自动机常常会遇到回溯的问题。回溯是指当一个匹配失败时,引擎会退回到前一个状态重新尝试匹配。这种回溯机制可能导致性能下降,尤其是在处理大量数据时。

如何避免回溯问题?

为了避免回溯问题,我们可以采用一些优化手段。以下是几种常见的优化技巧:

1、贪婪模式

在正则表达式中,默认情况下是贪婪模式,即匹配尽可能多的字符。在一些情况下,这可能会导致不必要的回溯。我们可以使用问号(?)来将贪婪模式转换为懒惰模式,从而减少回溯的可能性。

性能篇:String慎重使用正则表达式?_嵌套

在这个例子中,贪婪模式会匹配整个字符串,然后回溯,找到最后一个 "b"。为了避免这种情况,我们可以使用懒惰模式。

2、懒惰模式

懒惰模式与贪婪模式相反,它尽可能少地匹配字符。在某些情况下,懒惰模式能够有效减少回溯,提高匹配效率。

性能篇:String慎重使用正则表达式?_字符串_02

这样,它会匹配到第一个 "b",而不是整个字符串。这可以减少回溯的次数,提高匹配效率。

3、独占模式

除了贪婪模式和懒惰模式外,还有一种叫做独占模式。独占模式会尽可能匹配更长的字符串,但不会回溯。在正则表达式中,可以使用 \G 锚点来表示上一次匹配的结束位置。这样,匹配将从上一次匹配的结束位置开始,不会回溯。

性能篇:String慎重使用正则表达式?_嵌套_03

独占模式在某些情况下可以提高性能,但要小心使用,因为它可能导致意外的行为。

正则表达式优化

在实际编码中,我们可以通过一些优化策略来提高正则表达式的性能,特别是在处理大量数据时。以下是一些常见的优化方法:

1、少用贪婪模式,多用独占模式

贪婪模式虽然在某些情况下是必要的,但在不需要的情况下最好避免使用。多使用独占模式,能够有效减少回溯。

2、减少分支选择

正则表达式中的分支选择(使用 |)可能导致引擎不得不尝试多个路径。在可能的情况下,减少分支选择可以减少回溯的发生,提高匹配速度。

性能篇:String慎重使用正则表达式?_正则表达式_04

可以考虑重写为:

性能篇:String慎重使用正则表达式?_字符串_05

这样就避免了不必要的分支选择。

3、减少捕获嵌套

捕获嵌套指的是正则表达式中多个捕获组的嵌套使用。嵌套较深的捕获组可能导致性能下降,因为引擎需要跟踪多个捕获组的信息。

性能篇:String慎重使用正则表达式?_正则表达式_06

可以考虑简化为:

性能篇:String慎重使用正则表达式?_嵌套_07

这样可以减少嵌套捕获组的数量。

4、正向否定预查

正向否定预查是一种强大的工具,可以在不进行实际匹配的情况下判断字符串的某一部分是否不符合特定模式。例如,我们想匹配不包含"xyz"的字符串:

性能篇:String慎重使用正则表达式?_嵌套_08

这样,如果字符串中包含"xyz",整个表达式将不匹配,避免了回溯的发生。

5、条件匹配

条件匹配是一种根据特定条件选择不同匹配路径的方式。这可以通过 (?(condition)true-pattern|false-pattern) 实现。例如,我们想匹配奇数个"a",偶数个"b"的字符串:

性能篇:String慎重使用正则表达式?_正则表达式_09

这样,我们可以避免回溯,确保性能的稳定。

6、编译正则表达式

在实际使用中,将正则表达式编译成可重用的对象可能有助于提高性能。编译后的正则表达式可以在多次使用时避免重新解析,节省时间。

性能篇:String慎重使用正则表达式?_正则表达式_10

通过以上的优化策略,我们可以在保证正则表达式功能的基础上,尽可能提高匹配的效率,特别是在处理大规模数据时更为明显。

END

总结一下,正则表达式是编程中非常常见的工具,但在使用时我们也要注意其性能问题。通过选择合适的模式和优化策略,可以在不降低功能的情况下提高匹配的效率。希望大家在实际应用中能够灵活运用这些技巧,写出高性能的正则表达式。如果有任何问题或者建议,欢迎在评论区和我交流讨论哦!

本文到这里就结束啦,感谢大家的耐心阅读,希望对你有所帮助。如果喜欢我的文章,记得点个赞哦!我们下期再见,拜拜~

如有疑问或者更多的技术分享,欢迎关注我的微信公众号“知其然亦知其所以然”!

性能篇:String慎重使用正则表达式?_正则表达式_11

标签:匹配,String,NFA,正则表达式,模式,回溯,自动机,慎重
From: https://blog.51cto.com/u_16237826/9078828

相关文章

  • LeetCode-10 正则表达式匹配
    LeetCode-10正则表达式匹配给你一个字符串s和一个字符规律p,请你来实现一个支持'.'和'*'的正则表达式匹配。'.'匹配任意单个字符'*'匹配零个或多个前面的那一个元素所谓匹配,是要涵盖整个字符串s的,而不是部分字符串。示例1:输入:s="aa",p="a"输出:false解释:"a"......
  • 【JDK源码】String源码学习笔记
    代码运行环境:JDK8首先思考几个问题:String对象在不同的JDK中是如何实现的?String对象的不可变性是什么样的?下面这段代码的输出结果是什么?Strings1=newString("aaa")+newString("");s1.intern();Strings2="aaa";System.out.println(s1==s2);Strings3=newString("bbb......
  • JDK9中的String底层实现为什么用UTF-16而不用UTF-8呢?
    UTF-8是一种对空间利用效率最高的编码集,它是不定长的,使用1~4字节为每个字符编码。这种情况下,如果能用一个字节存放字符就不会使用两个字节,两个字节不够就用三个字节。这种编码集只适用于传输和存储,并不适合拿来做String的底层实现。String有随机访问的方法,比如charAt、subString等......
  • java基础知识点API之String详解--String基础看它就够了
    一:概述java中的String在java.lang包下,使用时可以直接使用不需要进行导包。字符串在日常使用中非常多,例如之前的变量定义。二:详细说明<1>JDK-帮助文档中对Strng类的介绍<2>字符串常量的创建,字符串常量在创建之后,它们的值不能被更改,但是可以被共享。publicstaticvoidmain(String[......
  • [CF1902E] Collapsing Strings
    题目链接考虑拆贡献。显然答案可以拆成对于所有\(s_i\)的每一个后缀的反串,作为前缀在所有串中的出现次数的加和。这个东西字典树维护一下就行了。不知道是谁考场上写哈希赛后被人对着模数卡掉了点击查看代码#include<bits/stdc++.h>#defineFL(i,a,b)for(inti=(a......
  • 【C/C++】通过下面的工作来改进String类声明(即将String1.h升级为String2.h)。 a. 对+运
    通过下面的工作来改进String类声明(即将String1.h升级为String2.h)。a.对+运算符进行重载,使之可将两个字符串合并成一个。b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。c.提供String()成员函数,将字符串中所有字母字符转换成大......
  • string
    pg有3种字符串类型。char(n):定长,不足用空格填补。省略n表示char(1)。varchar(n):变长,省略n表示任意长度,无限制。n是字符个数,不是字节个数。thelengthnmustbegreaterthanzeroandcannotexceed10,485,760.写入表字段的字符串长度超出n数据库会报错。text:不需要也无......
  • 无涯教程-Java 正则 - String replaceAll(String replacement)函数
    java.util.regex.Matcher.replaceAll(Stringreplacement)方法使用给定的替换字符串替换与该模式匹配的每个子序列。StringreplaceAll-声明publicStringreplaceAll(Stringreplacement)replacement  - 替换字符串。StringreplaceAll-返回值通过用替换字符串替......
  • 一个报错深刻理解axios传参和mock拦截(外加正则表达式)
    前言:事情是这样的,在使用axios二次封装和mock进行拦截的时候,不是参数传递方式不正确就是找不到后端接口,为此我茶不思饭不想把axios和mock好好看了一遍,最后除了这些问题,发现是输在了正则表达式上面,找出错误的时候自己都懵了axioa传参问题总所周知,我们在平时使用axios的时候是这样......
  • 无涯教程-Java 正则 - Matcher static String quoteReplacement(String s)函数
    java.time.Matcher.quoteReplacement(Strings)方法返回指定字符串的文字替换字符串。staticStringquoteReplacement-声明publicstaticStringquoteReplacement(Strings)s  - 要被字符串化的字符串。staticStringquoteReplacement-返回值文字字符串替换。......