正则表达式(**Reg**ular **Ex**pression)是用于检查给定字符串是否与该模式匹配的模式。
在 Ruby 中,正则表达式模式定义在两个斜杠之间(`/pattern/`)。例如,
# A regex pattern
/^m.t$/
上面的模式表示一个三字母字符串,其中:
- `^` - 标记字符串的开始(此处,字符串以 `m` 开头)。
- `.` - 表示任何一个字母或字符
- `$` - 标记字符串的结束(此处,字符串以 `t` 结尾)。
例如,字符串如 `"mat"` 和 `"mit"` 匹配上述正则表达式模式。
然而,像 `"mom"` 和 `"magnet"` 这样的字符串不匹配,因为这些字符串不是以 `m` 开头并以 `t` 结尾的 **3** 个字母单词。
Ruby 正则表达式类
Ruby 提供了 `Regex` 类来处理正则表达式。您可以使用**字面量语法**或 `Regexp.new` 方法来创建正则表达式模式。
语法
# Using literal syntax
/pattern/
# Using Regexp.new
Regexp.new("pattern")
此处,`pattern` 是您想匹配的正则表达式模式。
Ruby 中的正则表达式标志
正则表达式标志会修改模式的解释方式。它们被添加到正则表达式的结束斜杠之后。
一些常用的标志是:
- `i` - 大小写不敏感匹配
- `m` - 多行模式
让我们看一个例子,
/^m/i
此模式匹配以 `"m"` 或 `"M"` 开头的字符串。
示例:Ruby 正则表达式
# A regular expression pattern for a five-letter word
# that starts with "a" and ends with "e"
pattern = /^a...e$/
# Test string
word = "apple"
# Check if the word matches the pattern
if word.match?(pattern)
puts "String matches the pattern"
else
puts "String doesn't match the pattern"
end
输出
String matches the pattern
在上面的示例中,我们检查了字符串 `"apple"` 是否与定义的正则表达式模式匹配。
模式 `"^a...e$"` 表示任何以 `a` 开头并以 `e` 结尾的五字母字符串。
这里,`match?` 方法如果在我们传递的字符串与正则表达式模式匹配时返回 `true`。
如果我们传递另一个字符串,如 `"apache"`,它不会与 `pattern` 匹配,因为 `"apache"` 的字符数超过五位。
元字符
为了指定正则表达式,需要使用元字符。元字符是正则表达式引擎以特殊方式解释的字符。
一些基本元字符是:
元字符 | 描述 | 示例 |
---|---|---|
[] |
指定您希望匹配的字符集。 | /[abc]/ |
. |
指定任何单个字符(换行符 `'\n'` 除外)。 | /.../ |
^ |
指定字符串以某个字符开头。 | /^m/ |
$ |
指定字符串以某个字符结尾。 | /y$/ |
* |
匹配前面元素的零次或多次出现。 | /ca*t/ |
+ |
匹配前面元素的一次或多次出现。 | /ma+t/ |
? |
匹配前面元素的零次或一次出现。 | /ma?n/ |
{} |
指定前面元素的重复次数范围。 | /a{2}/ |
{} |
用作 `或` 运算符。 | /a|b/ |
() |
对正则表达式中的子模式进行分组。 | /(ab)+/ |
方括号:[]
``[]` 指定您希望匹配的字符集。例如,
/[abc]/
此模式匹配包含给定字符 `a`、`b` 或 `c` 中任何一个的字符串。
让我们检查以下字符串是否与正则表达式模式 `[abc]` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
“a” |
**1** 次匹配 | 字符串包含 `a`。 |
"ac" |
**2** 次匹配 | 字符串包含 `a` 和 `c`。 |
"jim" |
**0** 次匹配 | 字符串不包含 `a`、`b` 或 `c` 中的任何一个。 |
"abc" |
**3** 次匹配 | 字符串包含所有三个 - `a`、`b` 和 `c`。 |
**注意:** 您也可以使用方括号内的 `-` 来指定字符范围。例如,
[a-e]
与[abcde]
相同。- ``[0-3]` 与 `[0123]` 相同。
句点
句点表示任何单个字符(换行符 `'\n'` 除外)。例如,
/.../
上述模式匹配任何三个字符的子字符串(换行符除外)。
让我们检查以下字符串是否与正则表达式模式 `...` 匹配,该模式表示三个字符的组合。
字符串 | 匹配? | 原因 |
---|---|---|
"abs" |
**1** 次匹配 | 字符串包含三个字母(`a`、`b`、`s`)。 |
"ac" |
**0** 次匹配 | 字符串不包含三个字母。 |
"jim" |
**1** 次匹配 | 字符串包含三个字母。 |
"abcd" |
**1** 次匹配 | 字符串包含四个字母,其中前三个将被视为匹配。 |
"abcjkl" |
**2** 次匹配 | 字符串包含六个字母(**3+3**)。 |
插入符号:^
插入符号 `^` 指定字符串以某个字符开头。例如,
/^m/
此模式匹配以字母 `"m"` 开头的字符串。
让我们检查以下字符串是否与正则表达式模式 `^m` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"man" |
**1** 次匹配 | 它以 `"m"` 开头。 |
m |
**1** 次匹配 | 它以 `"m"` 开头。 |
Man |
**0** 次匹配 | 它不以 `"m"` 开头。 |
sms |
**0** 次匹配 | 它不以 `"m"` 开头。 |
美元符号:$
美元符号 `$` 指定字符串以某个字符结尾。例如,
/y$/
此模式匹配以字母 `"y"` 结尾的字符串。
让我们检查以下字符串是否与正则表达式模式 `y$` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"monday" |
**1** 次匹配 | 它以 `"y"` 结尾。 |
"say" |
**1** 次匹配 | 它以 `"y"` 结尾。 |
"myname" |
**0** 次匹配 | 它不以 `"y"` 结尾。 |
星号:*
星号 `*` 匹配前面元素的零次或多次出现。例如,
/ca*t/
这里,`a` 是 `*` 前面的元素。因此,此模式匹配 `c` 和 `t` 之间包含任意数量(包括零个)`a` 的字符串。
让我们检查以下字符串是否与正则表达式模式 `ca*t` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"cat" |
**1** 次匹配 | 它在 `c` 和 `t` 之间有一个 `a`。 |
"ct" |
**1** 次匹配 | 它在 `c` 和 `t` 之间没有 `a`。 |
"caaaat" |
**1** 次匹配 | 它在 `c` 和 `t` 之间有三个 `a`。 |
"crt" |
**0** 次匹配 | 它在 `c` 和 `t` 之间是字母 `r`(不是 `a`)。 |
"caatcaaat" |
**2** 次匹配 | 它在两个地方包含 `a`(`caat` 和 `caaat`)。 |
加号:+
加号 `+` 匹配前面元素的一次或多次出现。例如,
/ma+t/
此模式匹配 `m` 和 `t` 之间包含一个或多个 `a` 的字符串。
让我们检查以下字符串是否与正则表达式模式 `ma+t` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"mat" |
**1** 次匹配 | 它在 `m` 和 `t` 之间有一个 `a`。 |
"mt" |
**0** 次匹配 | 它在 `m` 和 `t` 之间没有 `a`。 |
"matemaat" |
**2** 次匹配 | 它有两个匹配的子字符串(`mat` 和 `maat`)。 |
"mart" |
**0** 次匹配 | `mart` 中的 `r` 后面没有 `t`。 |
问号:?
问号 `?` 匹配前面元素的零次或一次出现。例如,
/ma?n/
此模式匹配 `m` 和 `n` 之间包含一个或零个 `a` 的字符串。
让我们检查以下字符串是否与正则表达式模式 `ma?n` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"man" |
**1** 次匹配 | 它在 `m` 和 `n` 之间有一个 `a`。 |
"mn" |
**1** 次匹配 | 它在 `m` 和 `n` 之间有零个 `a`。 |
"maaaaan" |
**0** 次匹配 | 它在 `m` 和 `n` 之间有多个 `a`。 |
"woman" |
**1** 次匹配 | 它在 `m` 和 `n` 之间有一个 `a`。 |
花括号:{}
花括号 ` {} ` 用于指定前面元素的重复次数范围。
/a{2}/
此模式匹配连续两个 `a` 字符的字符串。
花括号 ` {} ` 可以用作:
# Exactly n times
{n}
# At least n times
{n,}
# Between n and m times
{n, m}
让我们检查以下字符串示例是否与正则表达式模式 `/a{2}/` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"aa" |
**1** 次匹配 | 它包含连续的两个 `a`。 |
"abcdaat" |
**1** 次匹配 | 它在其他字符的左侧有两个 `a`。 |
交替:|
竖线 `|` 用作 `或` 运算符。例如,
/a|b/
此模式匹配包含 `a` 或 `b` 的字符串。
让我们检查以下字符串是否与正则表达式模式 `a|b` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"cde" |
**0** 次匹配 | 它不包含 `a` 或 `b`。 |
"ade" |
**1** 次匹配 | 字符串中有一个 `a`。 |
"acdbea" |
**3** 次匹配 | 匹配字符串中的每个单独的 `a` 或 `b`。 |
括号:()
括号 ` () ` 用于对正则表达式中的子模式进行分组。
分组允许您将量词(如 `+`、`*` 或 `{}`)应用于整个组。例如,
/(ab)+/
此模式匹配子字符串 `"ab"` 的一次或多次出现。
让我们检查以下字符串是否与正则表达式模式 `(ab)+` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"ab" |
**1** 次匹配 | 它包含一次 `"ab"` 的出现。 |
"abab" |
**1** 次匹配 | 它有两个连续的 `"ab"` 序列。 |
"ababab" |
**1** 次匹配 | 它有三个连续的 `"ab"` 序列的单个长匹配。 |
"aabb" |
**0** 次匹配 | `"aa"` 打破了有效的重复组。 |
特殊序列
Ruby 正则表达式也支持常用字符集的特殊序列。
模式 | 描述 |
---|---|
\d |
任何数字(等同于 `[0-9]`) |
\D |
任何非数字 |
\w |
单词字符(字母、数字、下划线) |
\W |
非单词字符 |
\s |
空白字符 |
\S |
非空白字符 |
示例:匹配数字
`\d` 序列 ****在指定字符是一个或多个数字时匹配。例如,
/\d+/
此模式匹配一个或多个数字。
让我们检查以下字符串示例是否与正则表达式模式 `\d+` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"123" |
**1** 次匹配 | 字符串完全由数字组成,这些数字被组合在一起作为一个数字计数。 |
"a1b2c3" |
**3** 次匹配 | 分别匹配 **1**、**2** 和 **3**,因为它们之间有字母字符。 |
"abc" |
**0** 次匹配 | 没有数字。 |
转义序列
如果要匹配特殊字符(如 `.` 或 `*`),则需要使用反斜杠 `\` 对其进行转义。例如,
/\./
这匹配一个字面上的句点 `.`。
让我们检查以下字符串是否与正则表达式模式 `\.` 匹配。
字符串 | 匹配? | 原因 |
---|---|---|
"hello." |
**1** 次匹配 | 匹配字符串末尾存在的句点字符。 |
"hello" |
**0** 次匹配 | 没有句点。 |
"hi.." |
**2** 次匹配 | 匹配了两个字面上的句点。 |
Regex 方法
Ruby 提供了几种处理正则表达式的方法。
方法 | 描述 |
---|---|
=~ |
返回第一个匹配的索引或 `nil`。 |
匹配 |
返回 `MatchData` 对象或 `nil`。 |
match? (>= 2.4) |
如果找到匹配项则返回 `true`,否则返回 `false`。 |
scan |
返回所有匹配的子字符串的数组。 |
gsub |
替换所有匹配项。 |
示例:使用正则表达式方法
text = "I have 2 cats and 3 dogs"
# Find first match
# Output: 7
puts text =~ /\d/
# Get all digits
# Output: 2, 3
puts text.scan(/\d/).join(", ")
# Replace digits with '#'
# Output: I have # cats and # dogs
puts text.gsub(/\d/, '#')
正则表达式的用例
正则表达式常用于实际编程任务,例如:
- 验证输入格式(例如,电子邮件、电话号码)。
- 在文本中搜索特定关键字。
- 提取字符串的一部分(例如,数字、单词)。
- 将匹配的模式替换为新值。