Rust 正则表达式 Regex


使用:在 Cargo.toml文件中 [dependencies]下添加 regex
其他使用示例: https://rust-cookbook.budshome.com/text/regex.html

一、简单示例

(来自regex文档)

use regex::Regex;

// 常规日期查找
let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
assert!(re.is_match("2014-01-01"));

// 表达式反复与搜索字符串进行匹配
let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
let text = "2012-03-14, 2013-01-01 and 2014-07-05";
for cap in re.captures_iter(text) {
    println!("Month: {} Day: {} Year: {}", &cap[2], &cap[3], &cap[1]);
}
/* Output:
*  Month: 03 Day: 14 Year: 2012
*  Month: 01 Day: 01 Year: 2013
*  Month: 07 Day: 05 Year: 2014
*/


// 替换命名捕获
let re = Regex::new(r"(?x)
  (?P<y>\d{4}) # the year
  -
  (?P<m>\d{2}) # the month
  -
  (?P<d>\d{2}) # the day
").unwrap();
let before = "2012-03-14, 2013-01-01 and 2014-07-05";
let after = re.replace_all(before, "$m/$d/$y");
assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");


// 同时匹配多个常规表达式
let set = RegexSet::new(&[
    r"\w+",
    r"\d+",
    r"\pL+",
    r"foo",
    r"bar",
    r"barfoo",
    r"foobar",
]).unwrap();

// 迭代并收集所有匹配项
let matches: Vec<_> = set.matches("foobar").into_iter().collect();
assert_eq!(matches, vec![0, 2, 3, 4, 6]);

// 您还可以测试特定正则表达式是否匹配:
let matches = set.matches("foobar");
assert!(!matches.matched(5));
assert!(matches.matched(6));
use lazy_static::lazy_static;
use regex::Regex;


fn extract_login(input: &str) -> Option<&str> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"(?x)
            ^(?P<login>[^@\s]+)@
            ([[:word:]]+\.)*
            [[:word:]]+$
            ").unwrap();
    }
    // 【一】?P<login>   :命名捕获组:login
    // 【二】[^@\s]+     :不出现:@、空格
    // 【三】[[:word:]]+ :匹配[0-9a-zA-Z_]+
    //  第一行:命名捕获组,@前面不允许出现:@、空格(即@不重复,用户名不允许有空格)

    RE.captures(input).and_then(|cap|{
        cap.name("login").map(|login|login.as_str())
    })
}

fn main() {
    let text_01 = r"I❤email@example.com";
    let text_02 = r"sdf+sdsfsd.as.sdsd@jhkk.d.rl";
    let text_03 = r"Not_an_email@email";
    println!("text_01= {}",extract_login(&text_01).unwrap());
    println!("text_02= {}",extract_login(&text_02).unwrap());
    println!("text_03= {}",extract_login(&text_03).unwrap());

    assert_eq!(extract_login(r"More@Than@One@at.com"), None);
    assert_eq!(extract_login(r"Not an email@email"), None);
}

二、正则语法

此板条箱中支持的语法记录如下。正则语法

请注意,常规表达解析器和抽象语法暴露在一个单独的箱子中 regex-syntax.

匹配(一个)字符
.             # 除新行以外的任何字符(包括带有s标志的新行)
\d            # 数字 (\p{Nd})
\D            # 非数字

\pN           # 单字母名称Unicode字符类
\PN           # Negated(非) 单字母名称Unicode字符类

\p{Greek}     # Unicode字符类(常规类别或脚本)
\P{Greek}     # negated(非) Unicode字符类(常规类别或脚本)
[xyz]         # 匹配x、y或z(并集)的字符类。
[^xyz]        # 匹配 除x、y和z以外的 任何字符的字符类。
[a-z]         # 匹配A-z范围内任何字符的字符类。
[[:alpha:]]   # ASCII 字符类 ([A-Za-z])
[[:^alpha:]]  # Negated(非) ASCII 字符类 ([^A-Za-z])
[x[^xyz]]     # 嵌套/分组字符类(匹配除y和z以外的任何字符)
[a-y&&xyz]    # 交集(匹配x或y)
[0-9&&[^4]]   # 使用交集和求反的减法(匹配0-9,4除外)
[0-9--4]      # 直接减法            (匹配0-9,4除外)
[a-g~~b-h]    # 对称差异(范围异或)(仅匹配“a”和“h”)
[\[\]]        # 字符类中的转义(匹配[ 或 ])

任何命名的字符类都可能出现在括号字符类中。例如,匹配任何希腊语或 ASCII 数字。 匹配希腊字母。[...],[\p{Greek}[:digit:]],[\p{Greek}&&\pL]

字符类中的优先级,从最绑定到最少:

  1. 范围:a-cd == [a-c]d
  2. 并集:ab&&bc == [ab]&&[bc]
  3. 交集:^a-z&&b == ^[a-z&&b]
  4. 否定

复合

xy    串联(x后跟y)
x|y   交替 (x or y, 优先 x)
重复项, 空匹配
x*            # zero or more of x (greedy)         [0-n]个x (贪婪)
x+            # one or more of x (greedy)          [1-n]个x (贪婪)
x?            # zero or one of x (greedy)          [0-1]个x (贪婪)
x*?           # zero or more of x (ungreedy/lazy)     [0-n]个x (非贪婪/懒惰)
x+?           # one or more of x (ungreedy/lazy)      [1-n]个x (非贪婪/懒惰)
x??           # zero or one of x (ungreedy/lazy)      [0-1]个x (非贪婪/懒惰)
x{n,m}        # at least n x and at most m x (greedy)
x{n,}         # at least n x (greedy)
x{n}          # exactly n x
x{n,m}?       # at least n x and at most m x (ungreedy/lazy)
x{n,}?        # at least n x (ungreedy/lazy)
x{n}?         # exactly n x
^         # 文本的开头(或多行模式下的行首)
$         # 文本的结尾(或多行模式下的行尾)
\A        # 仅文本开头(即使启用多行模式)
\z        # 仅文本结尾(即使启用多行模式)
\b        # Unicode单词边界(一侧是\w,另一侧是\W、\A或\z)
\B        # 非Unicode单词边界
分组和标记
(exp)          编号捕获组(用括号开头索引)
(?P<name>exp)  命名(或编号)捕获组 (允许的字符: [_0-9a-zA-Z.\[\]])
(?:exp)        非捕获组 non-capturing group
(?flags)       在当前组中设置标志
(?flags:exp)   为exp(非捕获)设置标志 set flags for exp (non-capturing)

标志各为一个字符。例如,设置标志并清除标志。多个标志可以同时设置或清除:设置和标记,并设置标志并清除标志。(?x),x,(?-x),x,(?xy),x,y,(?x-y),x,y

除非另有说明,否则所有标志将默认禁用。它们是:

i         # 不区分大小写:字母匹配大小写
m         # 多行模式:^和$匹配行首/行尾
s         # 允许 . 匹配 \n
U         # 交换 x* 和 x*?
u         # Unicode支持(默认启用)
x         # 忽略空白并允许行注释(以“#”开头)

标志可以在模式内切换。下面是一个示例,该示例对第一部分案例的大小写不敏感,但第二部分案例的大小写敏感:

let re = Regex::new(r"(?i)a+(?-i)b+").unwrap();
let cap = re.captures("AaAaAbbBBBb").unwrap();
assert_eq!(&cap[0], "AaAaAbb");

请注意,匹配或,但唯一匹配。a+,a,A,b+,b

多行模式意味着不再仅在输入的开头/结束匹配,而是在输入的开头/结束匹配:^,$

let re = Regex::new(r"(?m)^line \d+").unwrap();
let m = re.find("line one\nline 2\n").unwrap();
assert_eq!(m.as_str(), "line 2");

请注意,匹配后的新行,即使在输入的末尾:^

let re = Regex::new(r"(?m)^").unwrap();
let m = re.find_iter("test\n").last().unwrap();
assert_eq!((m.start(), m.end()), (5, 5));

下面是一个使用 ASCII 单词边界而不是 Unicode 单词边界的示例:

let re = Regex::new(r"(?-u:\b).+(?-u:\b)").unwrap();
let cap = re.captures("$$abc$$").unwrap();
assert_eq!(&cap[0], "abc");
Escape-sequences
\*              # literal *, 适用于任何标点字符: \.+*?()|[]{}^$
\a              # bell (\x07)
\f              # form feed (\x0C)
\t              # horizontal tab
\n              # new line
\r              # carriage return
\v              # vertical tab (\x0B)
\123            # 八进制字符代码(最多三位数)(启用时)
\x7F            # 十六进制字符代码(精确两位)
\x{10FFFF}      # 与Unicode码位对应的任何十六进制字符代码
\u007F          # 十六进制字符代码(正好四位数)
\u{7F}          # 与Unicode码位对应的任何十六进制字符代码
\U0000007F      # 十六进制字符代码(正好八位数字)
\U{7F}          # 与Unicode码位对应的任何十六进制字符代码
Perl & ASCII 字符类
\d         # digit (\p{Nd})
\D         # not digit
\s         # whitespace (\p{White_Space})
\S         # not whitespace
\w         # word character (\p{Alphabetic} + \p{M} + \d + \p{Pc} + \p{Join_Control})
\W         # not word character
[[:alnum:]]        # alphanumeric ([0-9A-Za-z])
[[:alpha:]]        # alphabetic ([A-Za-z])
[[:ascii:]]        # ASCII ([\x00-\x7F])
[[:blank:]]        # blank ([\t ])
[[:cntrl:]]        # control ([\x00-\x1F\x7F])
[[:digit:]]        # digits ([0-9])
[[:graph:]]        # graphical ([!-~])
[[:lower:]]        # lower case ([a-z])
[[:print:]]        # printable ([ -~])             可打印
[[:punct:]]        # punctuation ([!-/:-@\[-`{-~]) 标点符号
[[:space:]]        # whitespace ([\t\n\v\f\r ])    空白
[[:upper:]]        # upper case ([A-Z])
[[:word:]]         # word characters ([0-9A-Za-z_])
[[:xdigit:]]       # hex digit ([0-9A-Fa-f])       十六进制数字
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值