首页 > 其他分享 >正则表达式-常见问题处理

正则表达式-常见问题处理

时间:2023-04-12 13:13:13浏览次数:36  
标签:常见问题 匹配 数字 正则表达式 可以 处理 正则 使用 写成

问题处理思路:

在讲解具体的问题前,我先来说一下使用正则处理问题的基本思路。有一些方法比较固定,比如将问题分解成多个小问题,每个小问题见招拆招:某个位置上可能有多个字符的话,就用字符组。某个位置上有多个字符串的话,就用多选结构。出现的次数不确定的话,就用量词。对出现的位置有要求的话,就用锚点锁定位置。

在正则中比较难的是某些字符不能出现,这个情况又可以进一步分成组中不能出现,和要查找的内容前后不能出现。后一种用环视来解决就可以了。我们主要说一下第一种。

如果是要查找的内容中不能出现某些字符,这种情况比较简单,可以通过使用中括号来排除字符组,比如非元音字母可以使用[^aeiou]来表示。

如果说内容中不能出现某个子串,比如要求密码是6位,且不能有连续两个数字出现。假设密码允许的范围是\w,你应该可以想到使用\w{6}来表示6位密码,但如果里面不能有连续两个数字的话,该如何限制呢?这个可以用环视来解决,就是每个字符的后面都不能是两个数字(要注意开头也不能是\d\d)。

常见问题及解决方案

1.匹配数字

    • 数字的匹配比较简单,通过我们学习的字符组,量词等就可以轻松解决。
    • 如果是连续的多个数字,可以使用\d+或[0-9]+
    • 如果n位数据,可以使用\d
    • 如果是至少n位数据,可以使用\d
    • 如果是m-n数字,可以使用\d

2.匹配正数、负数和小数

如果希望正则能匹配到比如3,3.14,-3.3,+2.7等数字,需要注意的是,开头的正负符号可能有,也可能没有,所以可以使用[-+]?来表示,小数点和后面的内容也不一定会有,所以可以使用(?:.\d+)来表示,因此匹配正数、负数和小数的正则可以写成[-+]?\d+(?:.\d+)?

![img](https://cdn.nlark.com/yuque/0/2023/png/10362390/1680680055408-e3a03ca7-ec2d-456f-bcb8-85bbc58bad33.png)

非负整数,包含0和正整数,可以表示成[1-9]\d*|0

非正整数,包含0和负整数,可以表示成-[1-9]\d*|0

3.浮点数

这个问题你可能觉得比较简单,其中表示正负的符号和小数点可能有,也可能没有,直接用[-+]?\d+(?:.\d+)?来表示

如果我们考虑.5和+.5这样的写法,但一版不会有-.5这样的写法。正则又如何写呢?

我们可以把问题拆解,浮点数分为符号位、整数部分、小数点和小数部分,这些部分都有可能不存在,如果我们每个部分都加个问号,这样整个表达式可以匹配上空。

根据上面的提示,负号的时候整数部分不能没有,而正数的时候,整数部分可以没有,所以正则你可以将正负两种情况拆开,使用多选结果写成 -?\d+(?:.\d+)?|+?(?:\d+

(?:.\d+)?|.\d+)

这个可以拆成两个问题:

负数浮点数表示:-\d+(?:.\d+)?

正数浮点数表示:+?(?:\d+(?:.\d+)?|.\d+)。

4.十六进制数

十六进制的数字除了有 0-9 之外,还会有 a-f(或 A-F) 代表 10 到 15 这 6 个数字,所以正则可以写成 [0-9A-Fa-f]+。

5.手机号码

手机号应该是比较常见的,手机号码比较复杂,如果要兼容所有的号段并不容易。目前来看,前四位是有一些限制,甚至1740和1741限制了前5位号段。

我们可以简单地使用字符组和多选分支,来准确地匹配手机号段。如果只限制前 2 位,可 以表示成 1[3-9]\d{9},如果想再精确些,限制到前三位,比如使用1(?:3\d|4[5-

9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[1389])\d{8}来表示。如果想精确到 4 位,甚至 5 位,可以根据公开的号段信息自己来写一下,但要注意的是,越是精确,只要 有新的号段,你就得改这个正则,维护起来会比较麻烦。另外,在实际运用的时候,你可能还要考虑一下有一些号码了 +86 或 0086 之类的前缀的情况。

手机号段的正则写起来其实写起来并不难,但麻烦的是后期的维护成本比较高,我之前就 遇到过这种情况,买了一个 188 的移动号码,有不少系统在这个号段开放了挺长时间之 后,还认为这个号段不合法。

6.身份证号码

我国的身份证号码是分两代的,第一代是 15 位,第二代是 18 位。如果是 18 位,最后一 位可以是 X(或 x),两代开头都不能是 0,根据规则,你应该能很容易写出相应的正则, 第一代可以用 [1-9]\d{14} 来表示,第二代比第一代多 3 位数据,可以使用量词 0 到 1 次,即写成 [1-9]\d{14}(\d\d[0-9Xx])?。

7.邮政编码

邮编一般为6位数字,首位不是0,比较简单,可以写成[1-9]\d{5},之前我们也提到过,6位数字在其它情况下出现可能性也非常大,比如手机号的一部分,身份证号的一部分,所以如果是数据提取,一般需要添加断言,即写成 (?<!\d)[1-9]\d{5}(?!\d)。

8.腾讯QQ号码

目前QQ号不能以0开头,最长的有10位,,最短的从 10000(5 位)开始。从规则上我

们可以得知,首位是 1-9,后面跟着是 4 到 9 位的数字,即可以使用 [1-9][0-9]{4,9} 来 表示。

9.中文字符

中文属于多字节 Unicode 字符,之前我们讲过比如通过 Unicode 属性,但有一些语言是不支持这种属性的,可以通过另外一个办法,就是码值的范围,中文的范围是 4E00 - 9FFF之间,这样可以覆盖日常使用大多数情况。

不同的语言是表示方式有一些差异,比如在 Python,Java,JavaScript 中,Unicode 可以写成 \u码值 来表示,即匹配中文的正则可以写成 [\u4E00-\u9FFF],如果在 PHP 中使用,Unicode 就需要写成 \u{码值} 的样式。下面是在 Python3 语言中测试的示例,你可以参考一下。

10.IPV4

IPv4 地址通常表示成 27.86.1.226 的样式,4 个数字用点隔开,每一位范围是 0-255,比如从日志中提取出 IP,如果不要求那么精确,一般使用 \d{1,3}(.\d{1,3}){3}就够了,需要注意点号需要转义。img
如果我们想要更精确地匹配,可以针对一到三位数分别考虑,一位数可以表示成0{0,2}\d,两位数可以表示成0?[1-9]\d,三位数可以表示成1\d\d|[0-4]\d|25[0-5],使用多选分支结构把他们写到一起,就是0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]这样

这是表示出了 IPv4 地址中的一位(正则假设是 X),我们可以把 IPv4 表示成 X.X.X.X,可 以使用量词,写成 (?:X.){3}X 或 X(?:.X){3},由于 X 本身比较复杂,里面有多选分支结构, 所以需要把它加上括号,所以 IPv4 的正则应该可以写成

(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?:.0{0,2}\d|0?[1- 9]\d|1\d\d|2[0-4]\d|25[0-5]){3}。

你以为这么写就对了么,如果你测试一下就发现,匹配行为很奇怪。

img

看到这个结果,你可能觉得太难了,不要担心,更不要放弃。其实我一开始也觉得这么写就可以了,我也需要测试,如果不符合预期,那就找到原因不断完善。

我们根据输出结果的表现,分析一下原因。原因主要有两点,都和多选分支结构有关系。 我们想的是所有的一到三位数字前面都有一个点,重复三次,但点号和 0{0,2}\d 写到一 起,意思是一位数字前面有点,两位和三位数前面没有点,所以需要使用括号把点挪出 去,最终写成(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?:.(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])){3}。

但是经过测试,还是会有问题,最后一个数字只匹配上了一位。

img

上一讲正则匹配原理中,我们讲解了 NFA 引擎在匹配多分支选择结构的时候,优先匹配最左边的,所以找到了一位数符合要求时,它就”急于“报告,并没有找出最长且符合要求的结果,这就要求我们在写多分支选择结构的时候,要把长的分支放左边,这样就可以解 决问题了,即正则写成(?:1\d\d|2[0-4]\d|25[0-5]|0?[1-9]\d|0{0,2}\d)

(?:.(?:1\d\d|2[0-4]\d|25[0-5]|0?[1-9]\d|0{0,2}\d)){3}。

11.日期和时间

假设日期格式是 yyyy-mm-dd,如果不那么严格,我们可以直接使用 \d{4}-\d{2}-\d{2}。 如果再精确一些,比如月份是 1-12,当为一位的时候,前面可能不带 0,可以写成 01 或 1,月份使用正则,可以表示成 1[0-2]|0?[1-9],日可能是 1-31,可以表示成 [12]\d|3[01]|0?[1-9],这里需要注意的是 0?[1-9] 应该放在多选分支的最后面,因为放最前面,匹配上一位数字的时候就停止了(示例),正确的正则(示例)应该是\d{4}-(?:1[0-2]|0?[1-9])-(?:[12]\d|3[01]|0?[1-9])。

时间格式比如是 23:34,如果是 24 小时制,小时是 0-23,分钟是 0-59,所以可以写成 (?:2[0-3]|1\d|0?\d)

标签:常见问题,匹配,数字,正则表达式,可以,处理,正则,使用,写成
From: https://www.cnblogs.com/xiaochenNN/p/17309447.html

相关文章

  • 正则表达式-笔记
    元字符元字符就是指那些在正则表达式中具有特殊意义的专用字符元字符的分类与记忆技巧我们可以把元字符大致分为这几类:表示单个特殊字符的,表示空白符的,表示某个范围的,表示次数的量词,另外还有表示断言的,我们可以把它理解成边界限定。特殊单字符.任意字符(换行除外)\d任意数......
  • 正则表达式-语言处理
    在进行文本处理时,正则解决的问题大概可以分成四类,分别是校验文本内容、提取文本内容、替换文本内容、切割文本内容。在这一节里,我会从功能分类出发,给你讲解在一些常见的编程语言中,如何正确地实现这些功能。校验文本内容我们先来看一下数据验证,通常我们在网页上输入的手机号、邮......
  • java事件处理机制
     事件源可以是一个键可以是一个鼠标可以是一个按钮.....发生了就是事件源事件就是事件的对象,当事件源发生了就会有事件对象(事件对象就会传递给事件监听者)事件监听者接受刀事件对象了之后会进行事件处理方法   ......
  • UVa 113 / POJ 2109 Power of Cryptography (使用double处理大整数&泰勒公式与误差分
    113-PowerofCryptographyTimelimit:3.000secondshttp://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=99&page=show_problem&problem=49http://poj.org/problem?id=2109题意:给出n和p,求出 ,但是p可以很大()如何存储p?不用大数可不可以?先看看double......
  • 常用的多边形处理库记录
    GeoPands Shapely pyproj Fiona rasterio 目前就收集到上面五个,详情见Python处理时空数据常用库案例及练习-CSDN博客。下面为它们的中文文档说明:shapely:Shapely用户手册—Shapely1.8.0文档(osgeo.cn)fiona:Fiona—Fiona2.0dev文档(osgeo.cn)......
  • 如何处理HTTP 503故障问题?
    简述HTTP503故障问题在业务管理上很常见, 以问题的可能性也相当多, 故障时除了503提示, 好像什么也没有, 发生故障时应如何处理呢? 文章内会为大家详细说明什么是HTTP503就是网站打不开时, 展示503错误等内容,503的内容又从那里来的呢? 真实情况是客户已成功连上网站服务器......
  • arroyo sql 处理
    我在arroyodocker镜像处理的时候简单说过一个arroyo的编译服务,在看了官方介绍之后发现官方是有说明的参考处理基于datafusion解析查询以及计划生成查询计划编译为arroyo逻辑dataflow计划dataflow逻辑计划,生成rust代码rust代码编译为将在arroyo工作节点的二进制文件......
  • spark stream冷启动处理kafka中积压的数据
    因为首次启动JOB的时候,由于冷启动会造成内存使用太大,为了防止这种情况出现,限制首次处理的数据量spark.streaming.backpressure.enabled=truespark.streaming.backpressure.initialRate=200forexample:#!/bin/shTaskName="funnel"UserName="hadoop"cd`dirname$0`nohupsudo......
  • 图像处理评价指标之模糊度(更新中)
    图像和视频在采集、压缩、传输、存储过程中,无可避免地会引入失真。模糊失真是图像、视频质量下降最主要的因素之一,研究图像模糊度评价方法有非常重要的意义。通过对模糊失真进行评测和度量,可以对整个图像传输或处理系统的质量进行监控,进而采取措施提高系统性能模糊度和清晰度概念图......
  • 基于Matlab的数字水印设计——基于空域的水印处理系统
    基于Matlab的数字水印设计——基于空域的水印处理系统原文链接:https://blog.csdn.net/yl624624/article/details/119966213MATLAB数字水印处理系统【LSB,界面GUI】摘要数字水印(DigitalWatermarking)技术是我们生活中经常见到的信息隐藏技术。它将一些标识信息(即数字水印......