正则表达式

一. 正则表达式语句

C++语句示例

#include <regex>
//匹配查找替换语法
regex r("[[:alpha:]]*Hello[[:alpha:]]*");//生成对象
regex_match(input_str, r)  //进行匹配,返回true和false
regex_search(input_str, r); //进行查找
regex_replace(input_str, r, "World") //进行替换

//表达式格式,\前都要再加一个\转义,大写取反
\d   表示 0~9 的任意一个数字
\w   表示任意一个大写或小写字母、数字或下划线
\s   表示空格或Tab
.    表示除\n和\r的任意一个字符
|    表示满足任意一个条件即可
[\s\S] 表示任意字符
[abc]  表示只要是abc中的一个就可以,进行范围限定
[^abc] 表示除abc外
[1-9]  表示从1到9的任意一个字符
{n}    表示匹配前面的表达式n次
{a,b}  表示匹配前面的表达式最少a次,最多b次
?      表示0次或1次
+      表示1次或多次
*      表示0次到多次

(?:)   表示非捕获组,捕获组可以使用\1\2来进行引用
(?=.*[a-z]) 至少包含小写字母

Python语句示例

import re
re.match(r'\s(\w*)\s(\w*).*',line)
re.search('(.*) (.*?) (.*)',line)
re.sub(pattern, repl, string, max=0)

二. 正则表达式实例

1. 重复的子字符串

检查串是否是由多个子串重复构成

regex re("(.*)\\1+"); //C++
regex re("(.+)\\1{1,}");//表示任意非空字符串,重复出现一次以上
return  True if re.match(r"^(.+)\1{1,}$", s) else False #Python,^表示开头,$表示结尾

2. 验证IP地址

//IPv4 1、根据"."分割开;2、四段;3、每段0-255;4、无前导0;5、全是digit
regex ipv4("^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$"); //250~255、200~249、100~199、0~99
//IPv6  1、根据":"分隔开;2、八段;3、1-4位;4、字母(abcdef)或者数字
regex ipv6("^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

3. 标签验证器

//起始标签、结束标签、标签仅含大写字母、长度1~9、内容不匹配<
regex tag(R"(<([A-Z]{1,9})>[^<]*</\1>)"); //这里重复第一个限定组标签
//格式为<![CDATA[]> 、其中内容可以包含任意字符
regex cdata(R"(<!\[CDATA\[.*?\]\]>)"); //*?表示非贪婪模式,尽快匹配第一个遇到的]]>
class Solution {
public:
    bool isValid(string code) {
        code = regex_replace(code, cdata, "#"); //先将不可解析的内容替换掉,后面要判断其是否在闭合标签间,不能直接删除
        for (string prev; prev != code; prev = exchange(code, regex_replace(code, tag, "~"))); //由于不替换<,这里会优先替换内圈的,然后替换外圈,最终把字符串变成一个~ 表示标签是嵌套的
        return code == "~"; 
    }
};

4. 删除注释

删除/**/和//的内容

// /**/处理全部内容,非贪婪匹配, //处理当前行内容,这里使用\n进行行分割
const regex re(R"(/\*[\s\S]*?\*/|//[^\n]*)");
class Solution {
public:
    vector<string> removeComments(vector<string>& source) {
        vector<string> ans;
        string s = "";
        for(auto &cur:source)
            s = s + cur + "\n"; //这里以\n为分割,限制\\的处理范围
        s = regex_replace(s, re, "");//处理字符串
        istringstream ss(s);//输入流
        while(getline(ss, s, '\n')) //以\n为分割批量接受处理过的字符串
            if (s.size()) ans.push_back(s); //非空字符串
        return ans;
    }
};

5. 驼峰式匹配

字符串中含有模板串的子序列,且其他字符都是小写字母

class Solution {
public:
    vector<bool> camelMatch(vector<string>& queries, string pattern) {
        vector<bool> ans;
        // "[a-z]*"s 初始化名为s的字符串, lambda函数使用右值引用来进行字符串的拼接,构建匹配模板串
        regex re(accumulate(pattern.cbegin(), pattern.cend(), "[a-z]*"s, [](auto&& s, char c) { return s + c + "[a-z]*"; }));
        transform(queries.cbegin(), queries.cend(), back_inserter(ans), [&re](auto&& s) { return regex_match(s, re); });
        return ans;
    }
};

6. IP地址无效化

用[.]替换.

regex re("\\.");
class Solution {
public:
    string defangIPaddr(string address) {
        return regex_replace(address, re, "[.]");
    }
};

7. 检查单词是否为句中其他单词的前缀

class Solution {
public:
    int isPrefixOfWord(string sentence, string searchWord, int ans = 0) {
        istringstream iss(sentence);
        return any_of(istream_iterator<string>(iss), istream_iterator<string>(), [&, tmp = regex(searchWord + ".*")](auto&& s) { ans++; return regex_match(s, tmp); }) ? ans : -1;
    }
};

8. 句子中的有效单词数

// 末尾标点符号(可能有)、中间连接符(可能有)、左右小写字母
regex re("([a-z]+(-[a-z]+)?)?[!,.]?$");

9. 强密码检测器II

//限定条件,至少八个字符、至少包含小写字母、大写字母、数字、特殊字符,同时不含两个连续相同字符
regex re(R"((?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()\-+])(?!.*(.)\1).{8,})");
posted @ 2023-08-03 17:14  失控D大白兔  阅读(7)  评论(0编辑  收藏  举报