常用的正则表达式

正则表达式中的分组(Groups in regexps)

首先,我们来介绍一个重要的概念:分组,这是我们在编写复杂正则表达式时需要用到的。分组的作用与数学表达式中的括号类似:它可以帮助我们设置操作的优先级

正则表达式的一部分可以用小括号括起来形成一个分组。我们也可以对每个分组应用量词(quantifier):如果你在括号后加上量词,它会应用于整个括号内的内容,而不是单个字符。

例如,下面的代码会查找文本中一对 “ho” 字符串的重复(一次或多次):

Java 示例
Pattern regexWithGroups = Pattern.compile("(ho)+");
String text = "ho hoho hohoho";
        
Matcher resultWithGroups = regexWithGroups.matcher(text);
while (resultWithGroups.find()) {
    System.out.println(resultWithGroups.group());
}
Kotlin 示例
val regexWithGroups = """(ho)+""".toRegex()
val text = "ho hoho hohoho"

val resultWithGroups = regexWithGroups.findAll(text)
for (res in resultWithGroups) println(res.value)

输出结果:

ho
hoho
hohoho

日期(Dates)

让我们从一个简单且常见的任务开始。假设你需要找出以下两种格式的日期:yyyy-mm-ddyyyy/mm/dd。怎么做?

我们需要匹配如下格式的文本:4 个数字,然后是一个可能的分隔符(/-),接着是 2 个数字相同的分隔符,再加 2 个数字。下面是实现这个目标的正则表达式:

\d{4}(-|\/)\d{2}\1\d{2}

解释:

  • \d{4}(-|\/):匹配 4 位数字,接着匹配一个分隔符(-/),并把它作为第一个分组

  • \d{2}\1:接下来匹配 2 位数字,后跟 第一个分组中提取的相同分隔符\1 表示第一个分组)。

  • 最后是 \d{2}:再匹配两个数字。

Java 示例
Pattern regex = Pattern.compile("\\d{4}(-|/)\\d{2}\\1\\d{2}");
String text = "Date 1: 2022-06-06" + 
              "Date 2: 2021/01/01; date 3: 2020-02-02";

Matcher dates = regex.matcher(text);
while (dates.find()) {
    System.out.println(dates.group());
}
Kotlin 示例
val regex = Regex("""\d{4}(-|\/)\d{2}\1\d{2}""")
val dates = regex.findAll("Date 1: 2022-06-06" +
        "Date 2: 2021/01/01; date 3: 2020-02-02")

for (date in dates) println(date.value)

输出结果:

2022-06-06
2021/01/01
2020-02-02

注意:这个正则表达式虽然有效,但在现实场景中可能不够健壮,它仅覆盖了少数几种格式。


电话号码(Phone numbers)

之前我们简单介绍过电话号的正则写法。现在我们来写一个稍微复杂一些的正则。

我们假设电话号码有如下格式之一:

  • XXX-XXX-XXXX

  • (XXX)-XXX-XXXX

  • (XXX)XXXXXXX

  • XXXXXXXXXX

以下是相应的正则表达式:

\(?[\d]{3}\)?-?[\d]{3}-?[\d]{4}

解释:

  • \(?[\d]{3}\)?-?:匹配前 3 个数字,可能有括号包裹,也可能有连字符。

  • [\d]{3}-?:匹配中间 3 位数字和可选的连字符。

  • [\d]{4}:匹配最后 4 位数字。

Java 示例
Pattern regex = Pattern.compile("\\(?\\d{3}\\)?-?\\d{3}-?\\d{4}");
String text = "Ann's phone: 123-345-6789 " +
              "Dave's phone: (111)-234-5678, and next phone is (101)-234-5000";

Matcher phones = regex.matcher(text);
while (phones.find()) {
    System.out.println(phones.group());
}
Kotlin 示例
val regex = Regex("""\(?[\d]{3}\)?-?[\d]{3}-?[\d]{4}""")
val phones = regex.findAll("Ann's phone: 123-345-6789 " +
        "Dave's phone: (111)-234-5678, and next phone is (101)-234-5000")

for (phone in phones) println(phone.value)

输出结果:

123-345-6789
(111)-234-5678
(101)-234-5000

邮箱(Email)

假设你需要找出文本中的所有邮箱地址。标准邮箱格式是 "用户名@子域.主域"。下面的正则表达式可以匹配大多数常规邮箱:

([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})

解释:

  • 第 1 组:([a-z0-9_\.-]+) 匹配用户名,可以包含小写字母、数字、下划线、点和连字符。

  • 然后是 @ 符号。

  • 第 2 组:([a-z0-9_\.-]+) 匹配域名,同样可以包含这些字符。

  • 然后是 .

  • 第 3 组:([a-z\.]{2,6}) 匹配顶级域名(2-6 个小写字母或点)。

Java 示例
String patternStr = "([a-z0-9_\\.-]+)@([a-z0-9_\\.-]+)\\.([a-z\\.]{2,6})";
Pattern regex = Pattern.compile(patternStr);
String text = "We have the following emails: abc@mail.com, joe_blow@address.ing";

Matcher matchResult = regex.matcher(text);
while (matchResult.find()) {
    System.out.println(matchResult.group());
}
Kotlin 示例
val regex = Regex("""([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})""")
val matchResult = regex.findAll("We have the following emails: " +
        "abc@mail.com, joe_blow@address.ing")

for (matches in matchResult) println(matches.value)

输出结果:

abc@mail.com
joe_blow@address.ing

URL(网址)

手动从文本中提取链接非常繁琐,但使用正则表达式就轻松多了!

URL 示例:https://www.somesite.com/index.html

以下正则可以匹配大多数 URL:

(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?

解释:

  • 第 1 组:(https?:\/\/)? 匹配 http://https://,是可选的。

  • 第 2 组 + 第 3 组:([\da-z\.-]+)\.([a-z\.]{2,6}) 匹配主机名和顶级域名。

  • 第 4 组:([\/\w\.-]*)*\/? 匹配路径部分(字母、数字、点、斜杠等)。

Java 示例
String patternStr = "(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w\\.-]*)*\\/?";
Pattern regex = Pattern.compile(patternStr);
String text = "Jet Brains Website: https://www.jetbrains.com/ " +
              "And here is information about Hyperskill: https://hi.hyperskill.org/how-we-teach";
        
Matcher matchResult = regex.matcher(text);
while (matchResult.find()) {
    System.out.println(matchResult.group());
}
Kotlin 示例
val regex = Regex("""(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?""")
val matchResult = regex.findAll("Jet Brains Website: https://www.jetbrains.com/ " +
        "And here is information about Hyperskill: https://hi.hyperskill.org/how-we-teach")

for (matches in matchResult) println(matches.value)

输出结果:

https://www.jetbrains.com/
https://hi.hyperskill.org/how-we-teach

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值