Rust语言中Regex正则表达式,匹配和查找替换等

官方仓库:https://crates.io/crates/regex

文档地址:regex - Rust 

github仓库地址:GitHub - rust-lang/regex: An implementation of regular expressions for Rust. This implementation uses finite automata and guarantees linear time matching on all inputs.

在线体验地址:Rust Playground

直接使用下面代码测试环境:

use regex::Regex;

fn main() {
    // try using the `regex` crate here
    let re = Regex::new(r"[1-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[1-9]{1,3}").unwrap();
    let text = "这是一段用于演示匹配的文本。192.168.0.1 是一个合法的 IP 地址,然而 900.300.700.600 不是.";
    for cap in re.captures_iter(text) {
        println!("匹配到合法的IP地址: {}", &cap[0]);
    }
}

点击左上角的RUN:就可以看到匹配结果

安装regex

直接在rust项目目录中运行:

cargo add regex

或者编辑 Cargo.toml 文件添加:

[dependencies]
regex = "1.10.4"

然后运行:cargo run

使用正则表达式

创建正则表达式对象:

let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();

1.是否匹配:is_match

判断字符串是否和正则表达式匹配,是的话返回true,不是的话返回false

use regex::Regex;

fn main() {
    println!("Hello, world!");
    //
    let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
    let date = "today is 2024-03-27";
    if re.is_match(date) {
        println!("完全匹配")
    } else {
        println!("不匹配")
    }
}

2.获取分组匹配到的项: captures_iter | captures

captures:返回与文本中最左边的第一个匹配相对应的捕获组。捕获组 0 始终对应于整个匹配。如果找不到匹配,则不返回任何内容。

captures_iter:返回文本中匹配的所有非重叠捕获组的迭代器。这在操作上与 find_iter 相同,除了它产生关于捕获组匹配的信息。

captures_iter可以获取到匹配到的每一项,可以通过遍历拿到匹配的结果,如果正则里面有使用分组()来匹配内容,可以通过遍历匹配的结果,通过下表来获取分组内容。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    for cap in re.captures_iter(date) {
        println!("匹配到的结果是:{}", &cap[0]);
    }
}


// 输出结果
匹配到的结果是:2024-03-27
匹配到的结果是:2023-11-23

不实用分组的匹配结果:captures (只能获取到匹配的第一个内容)

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    let res = re.captures(date).unwrap();
    println!("res is {}", &res[0]);
}



// 输出结果
res is 2024-03-27

 使用分组正则表达式获取分组后的匹配结果:

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    for cap in re.captures_iter(date) {
        println!("匹配到的结果是:{} {} {}", &cap[0], &cap[1], &cap[2]);
    }
}


// 输出结果
匹配到的结果是:2024-03-27 2024 03
匹配到的结果是:2023-11-23 2023 11

3.替换匹配的内容:replace  和  replace_all

replace是替换一次,replace_all是替换所有匹配到的内容。

replace替换一次:

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    let res = re.replace(date, "2020-02-11");
    println!("replace result is:{}", res);
}


// 输出结果
replace result is:today is 2020-02-11, yesterday is 2023-11-23

replace_all替换所有:

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    let res = re.replace_all(date, "2020-02-11");
    println!("replace result is:{}", res);
}


// 输出结果
replace result is:today is 2020-02-11, yesterday is 2020-02-11

4.查找正则匹配的内容:find 和 find_iter

find:返回文本中最左边第一个匹配的开始和结束字节范围。如果不存在匹配,则返回 None。请注意,这应该只在您想要发现匹配的位置时使用。如果使用 is_match,测试匹配的存在会更快。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    let res = re.find(date).unwrap();
    println!("find result is:{}", res.as_str());
}

// 输出
find result is:2024-03-27

find_iter:text中每个连续的非重叠匹配返回一个迭代器,返回相对于 text 的起始和结束字节索引。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
    let date = "today is 2024-03-27, yesterday is 2023-11-23";
    for fin in re.find_iter(date){
        println!("find result is:{}", fin.as_str());
    }
}


// 输出结果
find result is:2024-03-27
find result is:2023-11-23

5.分割匹配的内容:split 和 splitn

split:返回由匹配的正则表达式分隔的文本子字符串的迭代器。也就是说,迭代器的每个元素对应于正则表达式不匹配的文本。此方法不会复制给定的文本。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"[ \t]+").unwrap();
    let fields: Vec<&str> = re.split("a b \t  c\td    e").collect();
    println!("split result is:{:?}", fields)
}

// 输出结果
split result is:["a", "b", "c", "d", "e"]

splitn:返回最多有限个文本子字符串的迭代器,这些子字符串由正则表达式的匹配项分隔。(限制为0将不会返回任何子字符串。)也就是说,迭代器的每个元素对应于正则表达式不匹配的文本。字符串中未被拆分的剩余部分将是迭代器中的最后一个元素。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\W+").unwrap();
    let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
    println!("splitn result is:{:?}", fields)
}


// 输出结果
splitn result is:["Hey", "How", "are you?"]

高级或“低级”搜索方法

shortest_match:返回给定文本中匹配的结束位置。

该方法可以具有与 is_match 相同的性能特征,除了它提供了匹配的结束位置。特别是,返回的位置可能比通过 Regex::find 找到的最左边第一个匹配的正确结尾要短。

注意,不能保证这个例程找到最短或“最早”的可能匹配。相反,这个 API 的主要思想是,它返回内部正则表达式引擎确定发生匹配的点的偏移量。这可能因使用的内部正则表达式引擎而异,因此偏移量本身可能会改变。

通常,a+ 会匹配某个文本中 a 的整个第一个序列,但是shortest_match 一看到第一个 a 就会放弃:

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let text = "aaaaa";
    let pos = Regex::new(r"a+").unwrap().shortest_match(text).unwrap();
    println!("shortest match is:{}", pos)
}

// 输出结果
shortest match is:1

shortest_match_at:返回与 shortest_match 相同的值,但从给定的偏移量开始搜索。

起点的意义在于它考虑了周围的环境。例如,\A 定位点只能在 start == 0 时匹配。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d+").unwrap();
    // 在字符串中查找最短匹配
    let text = "123456789";
    let shortest_match = re.shortest_match_at(text, 0).unwrap();
    println!("Shortest match found at index {}", shortest_match);
}


// 输出结果
Shortest match found at index 1

is_match_at:返回与 is_match 相同的值,但从给定的偏移量开始搜索。

起点的意义在于它考虑了周围的环境。例如,\A 锚点只能在 start == 0 时匹配。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d{3}-\d{2}-\d{4}").unwrap();
    let s = "123-45-6789";
    // 使用is_match_at方法判断字符串是否匹配正则表达式
    if re.is_match_at(s, 0) {
        println!("Matched!");
    } else {
        println!("Not matched!");
    }
}


// 输出结果
Matched!

find_at:返回与 find 相同的值,但从给定的偏移量开始搜索。

起点的意义在于它考虑了周围的环境。例如,\A 锚点只能在 start == 0 时匹配。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let s = "hello world";
    let re = Regex::new(r"world").unwrap();
    // 使用find_at方法查找字符串中第一个匹配正则表达式的位置
    let pos = re.find_at(s, 0).unwrap().start();
    // 输出匹配位置
    println!("Match found at position: {}", pos);
}

// 输出结果
Match found at position: 6

辅助方法

as_str 方法:返回该正则表达式的原始字符串。

use regex::Regex;

fn main() {
    println!("Hello, world!");
    let re = Regex::new(r"\d+").unwrap();
    let text = "2021-08-01";
    let result = re.find(text).unwrap();
    println!("{}", result.as_str());
}


// 输出结果
2021

captures_len 方法:返回捕获的数量。 

正则匹配规则

下面说明了一些常用的正则匹配规则:

符号描述说明
^匹配一个字符串的起始字符如果多行标志被设置为 true,那么也匹配换行符后紧跟的位置。
$匹配一个字符串的结尾字符如果多行标志被设置为 true,那么也匹配换行符前的位置。
\b匹配一个单词的边界-
\B匹配单词边界相当于\b匹配的反集

限定符: 

符号描述说明
?匹配该限定符前的字符01等价于 {0,1},如 colou?r 可以匹配colourcolor
+匹配该限定符前的字符1等价于 {1,},如 hel+o可以匹配helohellohelllo、…
*匹配该限定符前的字符0等价于 {0,},如 hel*o可以匹配heohelohellohelllo、…
{n}匹配该限定符前的字符n如 hel{2}o只可以匹配hello
{n,}匹配该限定符前的字符最少n次如 hel{2,}o可以匹配hellohelllo、…
{n,m}匹配该限定符前的字符最少n次最多m次如 hel{2,3}o只可以匹配hello 和 helllo

单个字符:

符号描述说明
\d匹配任意数字
\s匹配任意空白符
\w匹配任意字母、数字、下划线、汉字等
\D匹配任意数字
\S匹配任意空白符
\W匹配除了字母、数字、下划线、汉字以外的字符
.匹配除了换行符以外的任意字符
形式描述说明
[A-Z]区间匹配,匹配字母表该区间所有大写字母[C-F]匹配字符C、D、E、F
[a-z]区间匹配,匹配字母表该区间所有小写字母[c-f]匹配字符c、d、e、f
[0-9]区间匹配,匹配该区间内的所有数字[3-6]匹配字符3、4、5、6
[ABCD]列表匹配,匹配[]中列出的所有字母如这里列出的A、B、C、D都会被匹配
[^ABCD]列表排除,匹配除了[]中列出的字符外的所有字符如这里列出的A、B、C、D都会被排除而匹配其它字符

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/494767.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode:2138. 将字符串拆分为若干长度为 k 的组(python3解法)

难度&#xff1a;简单 字符串 s 可以按下述步骤划分为若干长度为 k 的组&#xff1a; 第一组由字符串中的前 k 个字符组成&#xff0c;第二组由接下来的 k 个字符串组成&#xff0c;依此类推。每个字符都能够成为 某一个 组的一部分。对于最后一组&#xff0c;如果字符串剩下的…

【SAP2000】在框架结构中应用分布式面板荷载Applying Distributed Panel Loads to Frame Structures

在框架结构中应用分布式面板荷载 Applying Distributed Panel Loads to Frame Structures 使用"Uniform to Frame"选项,可以简单地将荷载用于更多样化的情况。 With the “Uniform to Frame” option, loads can be easily used for a greater diversity of situat…

如何高效阅读嵌入式代码

大家好&#xff0c;今天给大家介绍如何高效阅读嵌入式代码&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 高效阅读嵌入式代码需要一些技巧和实践经验。以下是一些建议&#xff…

Sublime 彻底解决中文乱码

1. 按ctrl&#xff0c;打开Console&#xff0c;输入如下代码&#xff1a; import urllib.request,os; pf Package Control.sublime-package; ipp sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHand…

excel统计分析——单向分组资料的协方差分析

参考资料&#xff1a;生物统计学 单向分组资料是具有一个协变量的单因素方差分析资料。 操作案例如下&#xff1a; 1、对x和y进行方差分析 由方差分析表可知&#xff1a;4种处理间&#xff0c;x存在显著差异&#xff0c;而y在处理间差异不显著。需要进行协方差分析&#xff0c…

【C语言】linux内核pci_iomap

一、pci_iomap /** pci_iomap 是一个用于映射 PCI 设备的 BAR&#xff08;Base Address Register&#xff0c;基地址寄存器&#xff09;的函数。* 此函数返回指向内存映射 IO 的指针&#xff0c;用于直接访问 PCI 设备的内存或 I/O 空间。* * 参数:* dev - 指向pci_dev结构的指…

IP如何异地共享文件?

【天联】 组网由于操作简单、跨平台应用、无网络要求、独创的安全加速方案等原因&#xff0c;被几十万用户广泛应用&#xff0c;解决了各行业客户的远程连接需求。采用穿透技术&#xff0c;简单易用&#xff0c;不需要在硬件设备中端口映射即可实现远程访问。 异地共享文件 在…

使用GO对PostgreSQL进行有意思的多线程压测

前言 针对PostgreSQL进行压缩&#xff0c;有很多相关的工具。有同学又要问了&#xff0c;为何还要再搞一个&#xff1f;比如&#xff0c;pgbench, sysbench之类的&#xff0c;已经很强大了。是的&#xff0c;它们都很强大。但有时候&#xff0c;在一些特殊的场景&#xff0c;可…

功能强大的国外商业PHP在线教育系统LMS源码/直播课程系统

功能强大的国外商业PHP在线教育系统LMS/在线教育市场源码/直播课程系统 Proacademy是在线教育一体化的解决方案&#xff0c;用于创建类似于Udemy、Skillshare、Coursera这种在线教育市场。 这个平台提供在线课程&#xff0c;现场课程&#xff0c;测验等等&#xff0c;并有一个…

单链表交叉分离,运用头插法,尾插法(算法库应用)

原文博客链接:单链表分离(头插法和尾插法的结合,理解指针变换)_3.对任务1或者2中创建的某一个单链表{a1,b1,a2,b2,...,an,bn},编写一个算法将-CSDN博客 函数实现: /************************************************** 函数名:separate_LinkList 功 能: 把一个链表,交叉新建…

如何在jupyter使用新建的虚拟环境以及改变jupyter启动文件路径。

对于刚刚使用jupyter的新手来说&#xff0c;经常不知道如何在其中使用新建的虚拟环境内核&#xff0c;同时&#xff0c;对于默认安装的jupyter&#xff0c;使用jupyter notebook命令启动 jupyter 以后往往默认是C盘的启动路径&#xff0c;如下图所示&#xff0c;这篇教程将告诉…

HBase的Python API操作(happybase)

一、Windows下安装Python库&#xff1a;happyhbase pip install happybase -i https://pypi.tuna.tsinghua.edu.cn/simple 二、 开启HBase的Thrift服务 想要使用Python API连接HBase&#xff0c;需要开启HBase的Thrift服务。所以&#xff0c;在Linux服务器上&#xff0c;执行…

软考数据库

目录 分值分布1. 事务管理1.1 事物的基本概念1.2 数据库的并发控制1.2.1 事务调度概念1.2.2 并发操作带来的问题1.2.3 并发控制技术1.2.4 隔离级别&#xff1a; 1.3 数据库的备份和恢复1.3.1 故障种类1.3.2 备份方法1.3.3 日志文件1.3.4 恢复 SQL语言 分值分布 1. 事务管理 1.…

读所罗门的密码笔记04_社会信用

1. 人工智能 1.1. 人工智能可以帮助人们处理复杂的大气问题&#xff0c;完善现有的气候变化模拟&#xff0c;帮助我们更好地了解人类活动对环境造成的危害&#xff0c;以及如何减少这种危害 1.2. 人工智能也有助于减少森林退化和非法砍伐 1.3. 人工智能甚至可以将我们从枯燥…

【数据结构】树、二叉树与堆(长期维护)

下面是关于树、二叉树、堆的一些知识分享&#xff0c;有需要借鉴即可。 一、初识树&#xff08;了解即可&#xff09; 1.树的概念 概念&#xff1a;一种非线性数据结构&#xff0c;逻辑形态上类似倒挂的树 树的构成&#xff1a;由一个根左子树右子树构成&#xff0c;其中子树…

springboot使用com.github.binarywang 包实现微信网页上的支付和退款

前提 微信小程序中实现微信支付是从小程序中调去微信支付的界面直接进行支付&#xff0c;那么在pc端需要实现微信的支付呢&#xff0c;是需要出现一个二维码让用户使用扫码支付的。 注意&#xff1a; 需要实现pc端的微信支付&#xff0c;需要在微信商户平台开通native支付&…

CUDA版本支持的pytorch版本

PyTorch 1.0.x - 支持 CUDA 7.5 PyTorch 1.1.x - 支持 CUDA 8.0 PyTorch 1.2.x - 支持 CUDA 9.0 PyTorch 1.3.x - 支持 CUDA 9.2 PyTorch 1.4.x - 支持 CUDA 10.1 PyTorch 1.5.x - 支持 CUDA 10.2 PyTorch 1.6.x - 支持 CUDA 11.0 PyTorch 1.7.x - 支持 CUDA 11.0/11.1 PyTorch…

QtCreator调试时无法显示std::string的内容

在银河麒麟V10或Ubuntu下使用QtCreator调试代码时&#xff0c;std::string类型变量在大多数情况下不显示实际内容&#xff0c;而是显示"<无法访问>"字样&#xff0c;鼠标点击进去也是看不见任何有用信息&#xff0c;这样非常影响调试效率&#xff0c;为此&…

Android-Handler详解_使用篇

本文我将从Handler是什么、有什么、怎们用、啥原理&#xff0c;四个方面去分析。才疏学浅&#xff0c;如有错误&#xff0c;欢迎指正&#xff0c;多谢。 1.是什么 因为Android系统不允许在子线程访问UI组件&#xff0c;否则就会抛出异常。所以咱们平实用的最多的可能是在子线…

国际伦敦金行情分析中的趋势分析方法

国际伦敦金行情走势复杂多变。近期&#xff0c;金价曾经一度刷新历史的新高点至2222&#xff0c;但就在当天&#xff0c;金价又快速下跌跌超过30美元。不过这么多变的伦敦金行情也为我们的交易创造了空间&#xff0c;有空间就等于有机会&#xff0c;只要我们能够掌握国际伦敦金…