惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tailwind CSS Blog
C
CERT Recently Published Vulnerability Notes
P
Proofpoint News Feed
Vercel News
Vercel News
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
Help Net Security
Help Net Security
月光博客
月光博客
N
News and Events Feed by Topic
Cloudbric
Cloudbric
博客园 - 司徒正美
L
LangChain Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tenable Blog
The Register - Security
The Register - Security
The Hacker News
The Hacker News
I
InfoQ
The Last Watchdog
The Last Watchdog
MyScale Blog
MyScale Blog
Schneier on Security
Schneier on Security
WordPress大学
WordPress大学
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
K
Kaspersky official blog
L
LINUX DO - 热门话题
N
News | PayPal Newsroom
F
Fortinet All Blogs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Security @ Cisco Blogs
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
C
Cisco Blogs
N
News and Events Feed by Topic
V2EX - 技术
V2EX - 技术
Latest news
Latest news
PCI Perspectives
PCI Perspectives
T
The Blog of Author Tim Ferriss
P
Palo Alto Networks Blog
T
Tor Project blog
Project Zero
Project Zero
云风的 BLOG
云风的 BLOG
Webroot Blog
Webroot Blog
Attack and Defense Labs
Attack and Defense Labs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

博客园 - 陈大欠

andrej karpathy skills 从 Harness Engineering 到 superpowers 从 Harness Engineering 到 OpenSpec 从 Harness Engineering 到 Trellis Harness Engineering copilot-api:让 ClaudeCode 接入 Github Copilot Claude Code Hooks 配置说明 Scoop Claude-LED MagicCenterHub Windows Terminal & PowerShell 玩转 Visual Studio 外部工具 WCF API 语义搜索工具 Step Builder:让对象构建有顺序、有边界、有校验 基于 Attribute 的 AOP 字段校验 浅析 .NET 响应式编程 IObservable与ReactiveX Cron表达式简明教程 快速批量升级 NugetPackage 版本 C# IEquatable和IEqualityComparer 最佳实践 使用XDT提高开发效率 如何保证XML正确性 分析 Dump 入门简明教程 Git commit emoji 对照表 ELK Stack 笔记 HTML5/CSS3(PrefixFree.js) 3D文字特效 Jquery实现图片上下一张 js css 构建滚动边框 使用jquery构建Metro style 返回顶部 使用js实现移动设备访问跳转到指定目录 从一幅图中了解开源世界 Jquery ajax 学习笔记 工欲善其事必先利其器系列之:在VS里面折叠js代码
正则表达式拾遗
陈大欠 · 2024-02-26 · via 博客园 - 陈大欠

正则表达式拾遗

正则介绍

正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regexregexpRE),是一种文本模式,包括普通字符(例如,az之间的字母)和特殊字符(称为“元字符”),是计算机科学的一个概念。正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符以及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本,许多程序设计语言都支持利用正则表达式进行字符串操作。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。正则表达式中的普通字符包括大小写字母、数字、标点符号及一些其他符号,元字符则是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。

正则表达式于20世纪40年代出现,用于描述常规语言,但直到20世纪70年代才出现在编程中,由肯·汤普逊编写的QED文字编辑器是编程中找到最早使用正则表达式的地方。正则表达式在许多场合中都有非常重要的应用,例如搜索、爬虫、数据验证等。

正则表达式的组成:

  1. 普通字符:包括大小写字母、数字、标点符号及一些其他符号。这些字符在正则表达式中表示它们自身,例如,正则表达式“hello”会匹配文本中的字符串“hello”
  2. 元字符:元字符是正则表达式中具有特殊意义的字符,它们并不表示自身,而是用来描述前导字符(或字符集合)在目标对象中的出现模式。常见的元字符包括:
  • “.”:匹配除了换行符以外的任意字符。
  • “*”:表示前面的字符可以出现任意次(包括0次)。
  • “?”:表示前面的字符可以出现0次或1次。
  • “+”:表示前面的字符可以出现至少1次。
  • “^”:匹配输入字符串的开始位置。
  • “$”:匹配输入字符串的结束位置。
  • “\d”:匹配一个数字字符,等价于[0-9]
  • “\D”:匹配一个非数字字符,等价于[^0-9]

正则表达式的应用:

  1. 搜索:正则表达式常用于在文本中搜索符合特定模式的字符串。例如,可以使用正则表达式在日志文件中搜索包含特定错误信息的行。
  2. 替换:正则表达式也可以用来替换文本中的字符串。例如,可以使用正则表达式将文本中的所有电话号码替换为特定的占位符。
  3. 验证:正则表达式可以用来验证输入是否符合特定的格式。例如,可以使用正则表达式验证电子邮件地址或电话号码的格式是否正确。

正则表达式的优点:

  1. 灵活性:正则表达式可以描述非常复杂的匹配模式,使得它在处理各种文本处理任务时非常灵活。
  2. 高效性:对于大量的文本数据,使用正则表达式可以显著提高处理效率。
  3. 广泛的应用:正则表达式被广泛应用于各种编程语言和文本处理工具中,使得它成为一种通用的文本处理技能。

然而,正则表达式也有其缺点,比如学习曲线较陡峭,需要一定的时间和精力来掌握;同时,过于复杂的正则表达式可能导致性能下降,需要谨慎使用。

熟能生巧用的多自然而然就懂了,重点就是多用。一开始也可以借助一些AI进行学习。

常用元字符关键字介绍

  • 字符类:
    • .:匹配除了换行符之外的任意单个字符。
    • \d:匹配任意数字,相当于 [0-9]
    • \D:匹配任意非数字字符,相当于 [^0-9]
    • \w:匹配任意字母、数字或下划线,相当于 [a-zA-Z0-9_]
    • \W:匹配任意非字母、数字或下划线字符,相当于 [^a-zA-Z0-9_]
    • \s:匹配任意空白字符(包括空格、制表符、换行符等)。
    • \S:匹配任意非空白字符。
  • 锚点:
    • ^:匹配输入字符串的开始位置。
    • $:匹配输入字符串的结束位置。
  • 量词:
    • *:匹配前面的子表达式零次或多次。
    • +:匹配前面的子表达式一次或多次。
    • ?:匹配前面的子表达式零次或一次。
    • {n}n 是一个非负整数,匹配确定的 n 次。
    • {n,}n 是一个非负整数,至少匹配 n 次。
    • {n,m}mn 均为非负整数,其中 n <= m,最少匹配 n 次且最多匹配 m 次。
  • 选择、分组和引用:
    • |:或操作符,匹配 | 前后任一表达式。
    • ():分组,将多个字符捆绑在一起,当作一个整体进行处理,也可以用于后向引用。
    • \n:后向引用,引用前面分组中捕获的文本(n 是一个正整数)。
  • 特殊字符转义:
    • \:转义字符,用于转义正则表达式中的特殊字符,如 \. 匹配 . 字符本身。
  • 字符集和否定字符集:
    • [...]:字符集,匹配方括号内的任一字符。
    • [^...]:否定字符集,匹配不在方括号内的任一字符。
  • 预定义模式,某些正则表达式引擎提供了一些预定义的字符类,如 \d\w 等。
    • i:不区分大小写匹配。
    • g:全局匹配,查找所有匹配项而不仅仅是第一个。
    • m:多行模式,让 ^$ 分别匹配每行的开头和结尾。

更多关键字请参考正则表达式语言 - 快速参考

.NET下正则使用

.NET 下的正则由 System.Text.RegularExpressions 相关类 提供的正则引擎。它也是比较强大的引擎,具体可以参考 正则表达式引擎/风味对比

检查一个字符串是否包含数字

string pattern = @"\d"; // 匹配任何数字  
string input = "abc123def";  
if (Regex.IsMatch(input, pattern))  
    Console.WriteLine("The string contains a number.");  
else  
    Console.WriteLine("The string does not contain a number.");  

从一个字符串中提取所有的单词

string pattern = @"\w+"; // 匹配一个或多个字母、数字或下划线  
string input = "Hello, world! This is a test.";  
MatchCollection matches = Regex.Matches(input, pattern);  
foreach (Match match in matches)  
    Console.WriteLine(match.Value);  

使用正则表达式替换字符串中的数字为

string pattern = @"\d"; // 匹配任何数字  
string input = "abc123def456";  
string replacement = "#";  
string result = Regex.Replace(input, pattern, replacement);  
Console.WriteLine(result); // 输出: abc###def###  

从字符串中提取电子邮件地址

string pattern = @"(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b)"; // 匹配电子邮件地址  
string input = "Contact us at info@example.com or support@website.org";  
MatchCollection matches = Regex.Matches(input, pattern);  
foreach (Match match in matches)  
    Console.WriteLine(match.Value); // 输出: info@example.com 和 support@website.org  

验证密码强度

  • 假设我们需要验证一个密码是否满足以下条件:
    • 至少包含一个大写字母
    • 至少包含一个小写字母
    • 至少包含一个数字
    • 长度至少为8个字符
string password = "Password123";  
string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$";  
if (Regex.IsMatch(password, pattern))  
    Console.WriteLine("密码强度足够。");  
else  
    Console.WriteLine("密码强度不足。");  

在这个正则表达式中:
(?=.*[a-z]) 是一个前瞻断言,确保字符串中至少有一个小写字母。
(?=.*[A-Z]) 确保至少有一个大写字母。
(?=.*\d) 确保至少有一个数字。
[a-zA-Z\d]{8,} 确保字符串至少由8个字符组成,且这些字符只能是字母或数字。

提取HTML标签中的文本

从HTML标签中提取文本。

string html = "<p>这是一个段落。</p><p>这是另一个段落。</p>";  
string pattern = @"<p>(.*?)</p>"; // 懒惰匹配防止跨标签匹配  
MatchCollection matches = Regex.Matches(html, pattern);  
foreach (Match match in matches)  
{  
    if (match.Success)  
        Console.WriteLine(match.Groups[1].Value); // 输出捕获组中的文本  
}  

在这个例子中,我们使用了懒惰量词 *? 来确保只匹配到最近的闭合标签 </p>。但是,请注意,正则表达式并不是解析HTML的最佳工具,因为它不能很好地处理嵌套的或不规则的HTML结构。对于实际的HTML内容提取,应该使用像HtmlAgilityPack这样的库。

匹配和替换日期格式

假设你有一个字符串,里面包含了多种日期格式,你想将它们统一成一种格式。例如,将 "dd/mm/yyyy""mm-dd-yyyy" 都转换成 "yyyy-mm-dd"

 string input = "我的生日是09/25/1990,但她的生日是25-09-1992。";  
string pattern1 = @"(\d{2})/(\d{2})/(\d{4})"; // 匹配 dd/mm/yyyy 格式  
string pattern2 = @"(\d{2})-(\d{2})-(\d{4})"; // 匹配 dd-mm-yyyy 格式  
    
string result = Regex.Replace(input, pattern1, "$3-$2-$1"); // 转换第一种格式  
result = Regex.Replace(result, pattern2, "$3-$2-$1"); // 转换第二种格式  
    
Console.WriteLine(result); // 输出: 我的生日是1990-09-25,但她的生日是1992-09-25。

手机号匹配

匹配国内手机号,或者海外手机号

string pattern = @"^(?:\(\+?86\))?1[0-9]{10}$|^(?!\(\+?86\))\(\+?[0-9]{1,4}\)[0-9-]+$";  
string[] phoneNumbers = new string[]
{  
    "(+86)13800138000",  
    "13800138000",  
    "(+123)456-7890",  
    "+4917612345678", // 这个号码不符合你的原始正则表达式,因为没有括号  
    "(+86)123456789012" // 故意放一个不符合的号码来测试  
};  

foreach (string phoneNumber in phoneNumbers)  
{  
    if (Regex.IsMatch(phoneNumber, pattern))  
        Console.WriteLine($"'{phoneNumber}' matches the pattern.");  
    else  
        Console.WriteLine($"'{phoneNumber}' does not match the pattern.");  
}  

正则验证工具

有很多正则在线验证工具

我们以这段正则举例
^(?:\(\+?86\))?1[0-9]{10}$|^(?!\(\+?86\))\(\+?[0-9]{1,4}\)(?:[0-9]+\-)*[0-9]+$
这段正则表达式可以分成两部分:

  1. (?:\(\+?86\))?1[0-9]{10}$:匹配中国手机号码,可以以"+86"开头,也可以不加区号,然后接11位数字。
  2. ^(?!\(\+?86\))\(\+?[0-9]{1,4}\)(?:[0-9]+\-)*[0-9]+$:匹配国际电话号码,不匹配以"+86"开头的号码,可以包含国际区号,然后是一系列数字和短横线,最后以数字结尾。

Regester

image

Regester是一款非常实用的正则表达式测试工具。以下是这款工具的主要功能和特点:

  • 多种结果查看方式:支持树形、表格、文本等三种结果查看方式,用户可以根据需要灵活选择。
  • 丰富的表格操作:表格内容不仅可以自由选择,还可以自由复制。此外,表格内容还可以导出为csv/xlsx文件,方便用户进行后续处理和分析。
  • 拖入文件作为匹配源文本:用户可以直接将需要测试的文件拖入软件界面,作为匹配源文本,无需手动复制粘贴。

正则可视化

菜鸟正则可视化

菜鸟正则可视化可以生成可视化正则解释图形。

image

PlantUML

PlantUML 是一种简单的文本语言,用于快速创建 UML 图。UML(统一建模语言)是一种广泛使用的图形表示法,用于建模、设计和构建软件系统。然而,创建 UML 图通常是一个繁琐的过程,需要专业的绘图工具。PlantUML 旨在通过提供一种简单的、易于学习的文本语法来解决这个问题,该语法可以直接转换为 UML 图。

使用 PlantUML,您可以在文本编辑器中编写描述 UML 图的代码,然后使用 PlantUML 工具或插件将其转换为图形表示。这种方法的优点是您可以在版本控制系统中轻松管理 UML 图,因为它们只是文本文件。此外,PlantUML 还支持多种 UML 图类型,包括类图、用例图、顺序图、活动图等。
我们可以使用它提供的Regex生成可视化图形。

@startregex
!theme cyborg
title MobileNumber
^(?:\(\+?86\))?1[0-9]{10}$|^(?!\(\+?86\))\(\+?[0-9]{1,4}\)(?:[0-9]+\-)*[0-9]+$
@endregex

image

常用正则

校验数字的表达式

正则表达式描述 正则表达式模
数字 ^[0-9]*$
n位的数字 ^\d{n}$
至少n位的数字 ^\d{n,}$
m-n位的数字 ^\d{m,n}$
零和非零开头的数字 ^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字 ^([1-9][0-9]*)+(\.[0-9]{1,2})?$
带1-2位小数的正数或负数 ^(\-)?\d+(\.\d{1,2})$
正数、负数、和小数 ^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数 ^[0-9]+(\.[0-9]{2})?$
有1~3位小数的正实数 ^[0-9]+(\.[0-9]{1,3})?$
非零的正整数 ^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数 ^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非负整数 ^\d+$ 或 ^[1-9]\d*|0$
非正整数 ^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数 ^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数 ^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数 ^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数 ^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

校验字符的表达式

正则表达式描述 正则表达式
英文和数字 ^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{440}$
长度为3-20的所有字符 ^.{320}$
由26个英文字母组成的字符串 ^[A-Za-z]+$
由26个大写英文字母组成的字符串 ^[A-Z]+$
由26个小写英文字母组成的字符串 ^[a-z]+$
由数字和26个英文字母组成的字符串 ^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串 ^\w+$ 或 ^\w{320}$
中文、英文、数字包括下划线 ^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号 ^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{220}$
可以输入含有^%&',;=?$"等字符 [^%&',;=?$\x22]+
禁止输入含有~的字符 [^~]+

特殊需求表达式

正则表达式描述 正则表达式
Email地址 ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名 [a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?
InternetURL [a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码 ^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$
电话号码 ^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码 \d{3}-\d{8}|\d{4}-\d{7}
电话号码正则表达式 ((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)
身份证号 (^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)
帐号是否合法 ^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码 ^[a-zA-Z]\w{5,17}$
强密码 ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,10}$
强密码 ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式 ^\d{4}-\d{1,2}-\d{1,2}
一年的12个月 ^(0?[1-9]|1[0-2])$
一个月的31天 ^((0?[1-9])|((1|2)[0-9])|30|31)$
xml文件 ^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式 [\u4e00-\u9fa5]
双字节字符 [^\x00-\xff]
空白行的正则表达式 \n\s*\r
HTML标记的正则表达式 <(\S*?)[^>]*>.*?|<.*? />
首尾空白字符的正则表达式 ^\s*|\s*$或(^\s*)|(\s*$)
腾讯QQ号 [1-9][0-9]{4,}
中国邮政编码 [1-9]\d{5}(?!\d)
IPv4地址 ((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}

钱的输入格式

正则表达式描述 正则表达式
有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000" ^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式 ^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号 ^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧。下面我们要加的是说明可能的小数部分 ^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的 ^[0-9]+(.[0-9]{2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样 ^[0-9]+(.[0-9]{1,2})?$
这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样 ^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须 ^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$

参考