scala
import re
# 1. 读取原文件
with open("address.txt", "r", encoding="utf-8") as f:
content = f.read()
# 2. 识别并替换手机号
# 正则匹配11位手机号,替换中间4位为####
processed_content = re.sub(
r"(\d{3})\d{4}(\d{4})", # 匹配规则:前3位+中间4位+后4位
r"\1####\2", # 替换为:前3位+####+后4位
content
)
# 3. 保存到新文件
with open("processed_address.txt", "w", encoding="utf-8") as f:
f.write(processed_content)
- 原内容(
address.txt):小花,xxx盛世城3楼303号,13617234567。 - 处理后(
processed_address.txt):小花,xxx盛世城3楼303号,136####4567。

scala
object reg04 {
def main(args: Array[String]): Unit = {
// 1. 读入文件。根目录下的address.txt
val source = scala.io.Source.fromFile("address.txt").mkString
// println(source)
// 2. 识别手机号
//val reg = "1[3456789]\d{9}".r
val reg = "(1[3456789])(\d{4})(\d{4})".r
// 3. 替换
// group 分组
// group(0) 匹配到的整个字符串
// group(1) 匹配到的第1个括号
// group(2) 匹配到的第2个括号
// group(3) 匹配到的第3个括号
val newSource = reg.replaceAllIn(source, m => {
println(m.group(0))
println(m.group(1))
println(m.group(2))
println(m.group(3))
m.group(1) + "*****" + m.group(3)
// println(m.toString)
// m.toString
})
// 4. 输出文件
val writer = new java.io.PrintWriter("address_new.txt")
writer.write(newSource)
writer.close()
}
}
scala
csharp
object reg04 {
- 定义一个 Scala 单例对象(
object),名为reg04,Scala 程序的入口逻辑通常写在单例对象中。
scala
arduino
def main(args: Array[String]): Unit = {
-
定义程序的主入口方法
main:args: Array[String]:接收命令行参数(本代码未使用);Unit:表示方法无返回值(类似 Java 的void)。
scala
ini
// 1. 读入文件。根目录下的address.txt
val source = scala.io.Source.fromFile("address.txt").mkString
-
读取文件内容:
scala.io.Source.fromFile("address.txt"):打开项目根目录下的address.txt文件,创建文件读取源;.mkString:将文件中的所有字符读取为一个完整的字符串,赋值给不可变变量source。
scala
arduino
// println(source)
- 注释掉的调试代码:打印原始文件内容,用于验证是否正确读取文件。
scala
ini
// 2. 识别手机号
//val reg = "1[3456789]\d{9}".r
val reg = "(1[3456789])(\d{4})(\d{4})".r
-
定义手机号匹配的正则表达式:
-
注释的
reg = "1[3456789]\d{9}".r:匹配完整的 11 位手机号(1开头 + 3/4/5/6/7/8/9 + 9 位任意数字),但未分组; -
生效的
reg = "(1[3456789])(\d{4})(\d{4})".r:-
用括号
()将手机号拆分为 3 个分组,方便后续替换:- 第 1 组
(1[3456789]):手机号前 3 位(运营商号段); - 第 2 组
(\d{4}):手机号中间 4 位(要打码的部分); - 第 3 组
(\d{4}):手机号后 4 位;
- 第 1 组
-
.r:将字符串转换为 Scala 的正则表达式对象。
-
-
scala
java
// 3. 替换
// group 分组
// group(0) 匹配到的整个字符串
// group(1) 匹配到的第1个括号
// group(2) 匹配到的第2个括号
// group(3) 匹配到的第3个括号
val newSource = reg.replaceAllIn(source, m => {
-
批量替换匹配到的手机号:
reg.replaceAllIn(source, 替换规则):在source字符串中,找到所有匹配reg的手机号,按规则替换;m => {...}:匿名函数(替换逻辑),m是每个匹配到的手机号的 "匹配对象",包含分组信息。
scala
scss
println(m.group(0))
println(m.group(1))
println(m.group(2))
println(m.group(3))
-
调试打印:输出每个匹配到的手机号的完整内容和分组内容,例如:
-
若匹配到
13617234567,则:m.group(0)→13617234567(完整手机号);m.group(1)→136(前 3 位);m.group(2)→1723(中间 4 位);m.group(3)→4567(后 4 位)。
-
scala
csharp
m.group(1) + "*****" + m.group(3)
-
核心替换逻辑:
- 拼接 "前 3 位 +
*****+ 后 4 位",替换原手机号; - 例如:
136+*****+4567→136*****4567。
- 拼接 "前 3 位 +
scala
arduino
// println(m.toString)
// m.toString
})
- 注释的调试代码:
m.toString等价于m.group(0),即打印完整匹配的手机号。
scala
go
// 4. 输出文件
val writer = new java.io.PrintWriter("address_new.txt")
writer.write(newSource)
writer.close()
-
保存处理后的内容:
new java.io.PrintWriter("address_new.txt"):创建打印写入器,指向新文件address_new.txt;writer.write(newSource):将替换后的字符串写入新文件;writer.close():关闭写入器,释放文件资源(必须执行,否则内容可能无法写入)。
scala
}
}
- 闭合
main方法和单例对象。
关键注意点
- 正则匹配范围:原代码的正则是 "非整行匹配",能识别嵌入在文本中的手机号(如 "小花 13617234567 地址"),而非仅独立一行的手机号;
- 打码符号 :代码中是
*****,若需改为####,只需把m.group(1) + "*****" + m.group(3)中的*****替换为####; - 编码问题 :原代码未指定文件编码,若文件包含中文,可能出现乱码,建议补充编码(如
fromFile("address.txt", "UTF-8")); - 资源释放 :
PrintWriter需手动close(),否则文件可能无法正常保存。