scala中正则表达式引用-手机号打码

49 阅读5分钟

(一)matches方法:全量验证字符串合法性

1. 方法核心介绍

正则表达式对象的 matches 方法,核心作用是验证给定的字符串是否完全满足正则表达式的匹配要求(即字符串从头到尾必须完整匹配正则规则,不能有多余字符),返回值为布尔类型(Booleantrue 表示符合规则,false 表示不符合规则),是数据格式校验的核心方法。

其标准使用格式如下:

// 格式:val 验证结果 = 正则表达式对象.matches(目标字符串)
val 结果: Boolean = reg.matches(目标字符串)

2. 基础示例(可直接运行)

import scala.util.matching.Regex

object RegexMatchesDemo {
    def main(args: Array[String]): Unit = {
        // 定义正则规则:匹配恰好3位数字
        val numReg: Regex = "\d{3}".r
        
        // 验证符合规则的字符串
        val validResult1 = numReg.matches("123")
        println("字符串"123"是否符合3位数字规则:" + validResult1) // 输出 true
        
        // 验证不符合规则的字符串(包含非数字字符)
        val invalidResult1 = numReg.matches("12a")
        println("字符串"12a"是否符合3位数字规则:" + invalidResult1) // 输出 false
        
        // 验证不符合规则的字符串(长度不足3位)
        val invalidResult2 = numReg.matches("12")
        println("字符串"12"是否符合3位数字规则:" + invalidResult2) // 输出 false
        
        // 验证不符合规则的字符串(长度超过3位)
        val invalidResult3 = numReg.matches("1234")
        println("字符串"1234"是否符合3位数字规则:" + invalidResult3) // 输出 false
    }
}

(二)实战案例:验证合法用户名

1. 需求背景

在论坛、电商平台、管理系统等用户注册场景中,为了保证用户名的规范性和可识别性,需要对用户输入的用户名进行格式校验,避免无效或不规范的用户名注册。

2. 合法用户名规则

**规则编号规则详情
规则 1字符构成合法:仅允许包含大小写英文字母(a-z、A-Z)、数字(0-9)以及下划线(_)
规则 2长度合规:用户名总长度限定在 6 到 12 位之间(既避免过短易重复,也避免过长不易记忆)
规则 3开头合规:不能以数字开头(防止用户名与纯数字 ID 混淆,提升辨识度)

3. 正则表达式编写与解读

(1)最终正则规则

^[a-zA-Z][a-zA-Z0-9_]{5,11}$

2)规则详细解读

正则片段片段解读
^行首锚点,限定匹配从字符串的开头开始(确保用户名开头无多余字符)
[a-zA-Z]用户名首字符:仅匹配大小写英文字母中的任意一个,满足 “不能以数字开头” 的规则
[a-zA-Z0-9_]用户名后续字符:匹配大小写英文字母、数字、下划线中的任意一个,满足 “字符构成合法” 的规则
{5,11}量词限定:表示前面的字符集需要出现 5 到 11 次。结合首字符的 1 位,总长度为 6(1+5)到 12(1+11)位,满足 “长度合规” 的规则
$行尾锚点,限定匹配到字符串的结尾结束(确保用户名结尾无多余字符)

4. 完整可运行代码(交互式校验)

object UsernameRegexValidationDemo {
    def main(args: Array[String]): Unit = {
        // 定义匹配合法用户名的正则表达式(严格遵循3条规则)
        val validUsernameReg = "^[a-zA-Z][a-zA-Z0-9_]{5,11}$".r
        
        // 标记程序是否持续运行
        var isRunning = true
        println("=== 用户名合法性校验工具 ===")
        println("规则:1. 6-12位长度;2. 以大小写字母开头;3. 仅包含字母、数字、下划线")
        println("输入任意内容进行校验,输入"exit"退出程序\n")
        
        // 循环接收用户输入,实现交互式校验
        while (isRunning) {
            print("请输入你要验证的用户名:")
            val userName = readLine().trim // 获取用户输入并去除首尾空格
            
            // 退出程序判断
            if (userName.equalsIgnoreCase("exit")) {
                isRunning = false
                println("程序已退出!")
            } else {
                // 调用matches方法进行合法性校验
                val isLegal = validUsernameReg.matches(userName)
                // 根据校验结果输出提示信息
                if (isLegal) {
                    println(s"✅ 用户名"$userName"符合要求,可以注册!")
                } else {
                    println(s"❌ 用户名"$userName"不符合要求,请重新输入!")
                }
            }
        }
    }
}

5. 测试用例参考

用户名校验结果原因分析
User_123合法(true)以大写字母 U 开头,长度 8 位,仅包含字母、数字、下划线
user123456合法(true)以小写字母 u 开头,长度 10 位,仅包含字母、数字
123User不合法(false)以数字 1 开头,违反规则 3
User_不合法(false)长度仅 5 位,违反规则 2
User123456789不合法(false)长度 13 位,违反规则 2
User@123不合法(false)包含特殊字符 @,违反规则 1

(三)replaceAllIn方法:正则批量替换文本

1. 方法核心介绍

replaceAllIn 是 Scala 正则表达式的核心替换方法,功能是在目标字符串中,查找所有匹配正则规则的子串,并将其替换为指定内容,最终返回替换后的全新字符串(原字符串不会被修改,Scala 字符串为不可变类型)。

其核心使用格式有两种:

(1)简单替换(固定内容替换)

 格式:val 替换后字符串 = 正则表达式对象.replaceAllIn(目标字符串, 固定替换内容)
val newStr: String = reg.replaceAllIn(targetStr, replaceStr)

(2)灵活替换(基于匹配结果动态替换)

/ 格式:val 替换后字符串 = 正则表达式对象.replaceAllIn(目标字符串, 匹配结果 => 动态替换逻辑)
val newStr: String = reg.replaceAllIn(targetStr, m => 自定义替换逻辑)

. 基础示例(固定内容替换)

需求:将目标字符串中所有的小写字母bc(连续)替换为01

object RegexReplaceBasicDemo {
    def main(args: Array[String]): Unit = {
        // 1. 定义正则规则:匹配连续的小写字母bc
        val bcReg = "bc".r
        
        // 2. 定义目标字符串
        val targetStr = "abcdabcdbcbc"
        
        // 3. 调用replaceAllIn方法进行固定替换
        val newStr = bcReg.replaceAllIn(targetStr, "01")
        
        // 4. 输出结果
        println(s"原字符串:$targetStr")
        println(s"替换后字符串:$newStr") 
        // 输出结果:a01da01d0101
    }
}

(四)实战案例:手机号中间 4 位打马赛克

1. 需求任务

在实际业务中(如用户信息展示、日志脱敏等场景),为了保护用户隐私,需要将手机号的中间 4-7 位(共 4 位)替换为星号(****),仅保留前 3 位和后 4 位。

例如:13812345678 → 138****5678

2. 实现思路

  1. 使用正则分组:将 11 位手机号分为 3 个分组(前 3 位 + 中间 4 位 + 后 4 位),对应正则表达式 (\d{3})(\d{4})(\d{4})
  2. 调用 replaceAllIn 方法:基于分组结果动态替换,保留分组 1(前 3 位)和分组 3(后 4 位),将分组 2(中间 4 位)替换为 ****

3. 完整可运行代码

import scala.util.matching.Regex

object PhoneNumberMaskDemo {
    def main(args: Array[String]): Unit = {
        // 1. 定义包含多个手机号的目标文本
        val originalText = 
            """
              |用户1:手机号13812345678
              |用户2:手机号13987654321
              |用户3:手机号18612345678
              |用户4:手机号17798765432
              |""".stripMargin
        
        // 2. 定义手机号分组正则规则:(前3位)(中间4位)(后4位)
        val phoneRegex: Regex = "(\d{3})(\d{4})(\d{4})".r
        
        // 3. 调用replaceAllIn方法,基于分组动态打马赛克
        val maskedText = phoneRegex.replaceAllIn(originalText, m => {
            // m.group(1):获取第一个分组(前3位手机号)
            // m.group(3):获取第三个分组(后4位手机号)
            // 中间拼接****,实现脱敏
            m.group(1) + "****" + m.group(3)
        })
        
        // 4. 输出结果对比
        println("=== 手机号脱敏前后对比 ===")
        println("【脱敏前】:")
        println(originalText)
        println("【脱敏后】:")
        println(maskedText)
    }
}

4. 关键说明

  1. 正则分组与group方法

    • 正则表达式中的 () 对应分组索引,索引从 1 开始(group(0) 表示整个匹配的手机号,如13812345678);
    • m.group(1) 对应第一个分组 (\d{3}),即手机号前 3 位;
    • m.group(2) 对应第二个分组 (\d{4}),即手机号中间 4 位(需要替换的部分);
    • m.group(3) 对应第三个分组 (\d{4}),即手机号后 4 位。
  2. 运行结果:所有手机号均会实现脱敏,例如 13812345678 变为 138****567813987654321 变为 139****4321,有效保护用户隐私。

  3. 扩展性:若需调整脱敏位数(如中间 5 位打码),只需修改正则分组和替换逻辑即可,例如正则改为 (\d{3})(\d{5})(\d{3}),替换为 m.group(1) + "*****" + m.group(3)