简介
本教程将向你介绍 Bash 中的正则表达式(regex)。正则表达式是用于在文本中查找模式的强大工具。通过学习正则表达式,你将大大提高你的 shell 脚本编写技能,从而能够更有效地处理文本、提取数据和自动化任务。本教程专为初学者设计,因此无需具备正则表达式的先验经验。我们将从基础开始,逐步积累你的知识。
理解基本正则表达式和匹配
让我们从正则表达式的基本概念开始。正则表达式是定义一个 搜索模式 的字符序列。你可以把它看作是一种非常强大的文本搜索方式。
以下是基本的构建块:
- 字面字符: 大多数字符只匹配它们本身。例如,正则表达式
abc将精确匹配字符串 "abc"。 - 元字符: 这些是在正则表达式中有特定含义的特殊字符。让我们来看看几个关键的元字符:
.(点):匹配 _任意单个字符_(换行符除外)。因此,a.c可以匹配 "abc"、"axc"、"a1c" 等等。*(星号):匹配 _前一个字符零次或多次_。ab*c可以匹配 "ac"、"abc"、"abbc"、"abbbc" 等。^(脱字符):匹配 _行的开头_。^hello将匹配以 "hello" 开头的行。$(美元符号):匹配 _行的结尾_。world$将匹配以 "world" 结尾的行。[](方括号):定义一个 _字符类_。它匹配方括号内的 任意一个 字符。[abc]可以匹配 "a"、"b" 或 "c"。[0-9]匹配任意单个数字。
现在,让我们创建一个 Bash 脚本来测试我们的理解。使用 touch 命令创建一个名为 regex_test.sh 的文件:
cd ~/project
touch regex_test.sh
接下来,使用文本编辑器(如 nano 或 vim)打开 regex_test.sh 并添加以下代码:
#!/bin/bash
string="Hello World"
if [[ "$string" =~ ^Hello ]]; then
echo "The string starts with Hello"
else
echo "The string does not start with Hello"
fi
保存文件并使其可执行:
chmod +x regex_test.sh
最后,运行脚本:
./regex_test.sh

输出应该表明该字符串以 "Hello" 开头。
在脚本中使用字符集
使用方括号 [] 定义的字符集允许你从特定组中匹配一个字符。这对于创建更灵活的模式非常有用。
- 字符范围: 在
[]内,你可以使用连字符 (-) 来指定一个范围。[a-z]匹配任何小写字母,[A-Z]匹配任何大写字母,[0-9]匹配任何数字。你可以将它们组合起来:[a-zA-Z0-9]匹配任何字母数字字符。 - 取反: 如果你将
^作为[]内的 第一个 字符,它会对该字符类进行 _取反_。[^0-9]匹配任何 非 数字字符。
让我们修改我们的 regex_test.sh 脚本以使用字符集。使用文本编辑器打开 regex_test.sh 并将其内容替换为以下内容:
#!/bin/bash
string="cat"
if [[ "$string" =~ c[a-z]t ]]; then
echo "Match found!"
else
echo "No match."
fi
保存文件并运行它:
./regex_test.sh
输出应该显示 "Match found!"。这是因为 c[a-z]t 匹配任何以 'c' 开头、以 't' 结尾的三个字母的字符串,其中中间字符是小写字母。
在脚本中使用量词重复模式
量词用于控制一个字符或字符组应该重复的次数。这极大地增强了你的正则表达式模式的功能。
+(加号):匹配前一个字符 _一次或多次_。ab+c可以匹配 "abc"、"abbc"、"abbbc" 等,但 不 匹配 "ac"。?(问号):匹配前一个字符 _零次或一次_(即让前一个字符可选)。ab?c可以匹配 "ac" 和 "abc",但不匹配 "abbc"。*(星号):匹配前一个字符 _零次或多次_。我们之前已经见过这个。{n}:精确匹配前一个字符 _n 次_。a{3}匹配 "aaa"。{n,}:匹配前一个字符 _n 次或更多次_。a{2,}匹配 "aa"、"aaa"、"aaaa" 等。{n,m}:匹配前一个字符 _n 到 m 次_(包含 n 和 m)。a{1,3}匹配 "a"、"aa" 或 "aaa"。
让我们修改 regex_test.sh 脚本以使用量词。用文本编辑器打开 regex_test.sh 并将其内容替换为以下代码:
#!/bin/bash
string="abbbc"
if [[ "$string" =~ ab+c ]]; then
echo "Match found!"
else
echo "No match."
fi
保存文件并运行它:
./regex_test.sh
输出应该显示 "Match found!"。这是因为 ab+c 匹配以 'a' 开头,后面跟着一个或多个 'b',并以 'c' 结尾的字符串。
在脚本中使用捕获组提取数据
括号 () 用于对正则表达式的部分进行 _分组_。这对于将量词应用于多个字符以及 捕获 匹配的文本非常有用。
当你使用括号时,Bash 会将正则表达式中该部分匹配的文本存储在一个名为 BASH_REMATCH 的特殊数组中。BASH_REMATCH[0] 包含整个匹配的字符串,BASH_REMATCH[1] 包含第一个捕获组匹配的文本,BASH_REMATCH[2] 包含第二个捕获组匹配的文本,依此类推。
让我们修改 regex_test.sh 脚本,使用捕获组来提取数据。用文本编辑器打开 regex_test.sh,并将其内容替换为以下代码:
#!/bin/bash
string="apple123"
if [[ "$string" =~ ^([a-z]+)([0-9]+)$ ]]; then
fruit="${BASH_REMATCH[1]}"
number="${BASH_REMATCH[2]}"
echo "Fruit: $fruit"
else
echo "No match."
fi
保存文件并运行它:
./regex_test.sh
输出应该包含 "Fruit: apple"。此脚本使用捕获组从字符串中提取水果名称。
在脚本中使用 sed 替换文本
让我们创建一个名为 sed_test.sh 的新脚本,来练习使用 sed。
cd ~/project
touch sed_test.sh
chmod +x sed_test.sh
用文本编辑器打开 sed_test.sh 并添加以下内容:
#!/bin/bash
string="apple123"
echo "$string" | sed 's/[0-9]/X/g'
保存文件并运行它:
./sed_test.sh
输出应该是:appleXXX。此脚本使用 sed 将字符串中的所有数字替换为字母 "X"。
总结
本教程向你介绍了 Bash 中的正则表达式(regex)。你学习了基本的正则表达式概念、字符类、量词、分组、捕获,以及如何将正则表达式与 sed 结合使用。通过编写和执行 Bash 脚本,你已经获得了使用这些强大工具的实践经验。请记住通过练习和尝试不同的正则表达式模式来巩固你的理解。



