1. 前言
在 C 语言中,处理字符串是一项非常重要的工作。而正则表达式可以帮助我们更加优雅的处理字符串。本文将介绍如何在 Linux C 中使用正则表达式来处理字符串。文章从什么是正则表达式开始,逐步引入 C 语言中正则表达式的使用方法,介绍了常见的正则表达式匹配函数。
2. 正则表达式简介
2.1 什么是正则表达式
正则表达式是一种字符串匹配模式,用于检索文本中符合给定模式的字符串。可以通过使用正则表达式来执行搜索、替换等操作。
正则表达式是由特殊字符和普通字符组成的表达式,特殊字符具有特殊的含义,用于表示一类字符,而普通字符则表示单个字符。例如,字符类 [] 匹配其中任意一个字符,量词符 * 表示匹配前面的字符出现 0 次或多次。
2.2 正则表达式常用语法
下表列举了正则表达式中常用的语法:
语法 | 描述 |
---|---|
. | 匹配任意单个字符,除了换行符和行结束符 |
[...] | 匹配方括号中的任意单个字符 |
[^...] | 匹配不在方括号中的任意单个字符 |
^ | 匹配字符串开始位置 |
$ | 匹配字符串结束位置 |
* | 匹配前面的字符出现零次或多次 |
+ | 匹配前面的字符出现一次或多次 |
? | 匹配前面的字符出现零次或一次 |
{n} | 匹配前面的字符恰好出现 n 次 |
{n, m} | 匹配前面的字符至少出现 n 次,至多出现 m 次 |
(...) | 匹配圆括号中的任意表达式,并将其作为一个分组 |
| | 匹配 | 左侧或右侧的任意表达式 |
\ | 用于转义特殊字符 |
2.3 正则表达式实例
下表列举了一些常用的正则表达式实例:
正则表达式 | 描述 |
---|---|
^[a-z]+$ | 匹配只包含小写字母的字符串 |
^(http:\/\/|https:\/\/)[a-zA-Z0-9]+\.[a-zA-Z0-9]+\.[a-zA-Z0-9]+$ | 匹配以 http:// 或 https:// 开头,中间有一个或多个字母数字字符,以 . 分隔,以字母数字字符结束的字符串 |
^\d{3}-\d{2}-\d{4}$ | 匹配美国的社会安全号码格式:###-##-#### |
3. Linux C 中的正则表达式
3.1 regex.h 头文件
C 语言的正则表达式库在头文件 regex.h 中。该库提供了多个函数,可用于处理正则表达式匹配。
3.2 正则表达式匹配函数
下面是 regex.h 中常用的正则表达式匹配函数:
regcomp()
regexec()
regerror()
regfree()
regcomp() 函数用于编译正则表达式为一个内部格式,以便后续使用。regexec() 函数用于执行匹配操作。如果一个字符串匹配了正则表达式,那么 regexec() 函数将返回 0,否则将返回一个非零值。regerror() 函数用于打印关于错误的信息。regfree() 函数用于释放由 regcomp() 函数分配的内存。
4. 示例代码
4.1 匹配 IP 地址
下面的代码演示了如何使用正则表达式匹配 IP 地址:
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main()
{
char *str = "192.168.1.1";
regex_t regex;
int reti;
char msgbuf[100];
// 编译正则表达式
reti = regcomp(®ex, "^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
// 执行匹配操作
reti = regexec(®ex, str, 0, NULL, 0);
if (!reti) {
printf("%s is a valid IP address\n", str);
} else if (reti == REG_NOMATCH) {
printf("%s is not a valid IP address\n", str);
} else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
// 释放内存
regfree(®ex);
return 0;
}
该代码使用正则表达式 ^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$ 匹配一个 IP 地址。其中,\\d 表示一个数字字符,{n,m} 表示前面的字符出现 n 次到 m 次。这个正则表达式可以匹配类似 192.168.1.1 这样的 IP 地址,而不能匹配例如 192.168.01.1 这样的非法 IP 地址。
4.2 匹配手机号码
下面的代码演示了如何使用正则表达式匹配手机号码:
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main()
{
char *str = "13001234567";
regex_t regex;
int reti;
char msgbuf[100];
// 编译正则表达式
reti = regcomp(®ex, "^(1[3456789]\\d{9})$", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
// 执行匹配操作
reti = regexec(®ex, str, 0, NULL, 0);
if (!reti) {
printf("%s is a valid phone number\n", str);
} else if (reti == REG_NOMATCH) {
printf("%s is not a valid phone number\n", str);
} else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
// 释放内存
regfree(®ex);
return 0;
}
该代码使用正则表达式 ^(1[3456789]\\d{9})$ 匹配一个手机号码。其中,1[3456789] 表示手机号码的前三位是 13、14、15、16、17、18 或 19。\\d 表示任意一个数字字符,{9} 表示前面的字符出现 9 次。这个正则表达式可以匹配类似 13001234567 这样的手机号码,而不能匹配例如 12000123456 这种非法手机号码。
4.3 匹配邮箱地址
下面的代码演示了如何使用正则表达式匹配邮箱地址:
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main()
{
char *str = "john.doe@gmail.com";
regex_t regex;
int reti;
char msgbuf[100];
// 编译正则表达式
reti = regcomp(®ex, "^([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})$", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
// 执行匹配操作
reti = regexec(®ex, str, 0, NULL, 0);
if (!reti) {
printf("%s is a valid email address\n", str);
} else if (reti == REG_NOMATCH) {
printf("%s is not a valid email address\n", str);
} else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
// 释放内存
regfree(®ex);
return 0;
}
该代码使用正则表达式 ^([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})$ 匹配一个邮箱地址。其中,[a-zA-Z0-9._%+-] 匹配任意一个字母、数字、点、下划线、百分号、加号、减号。@[a-zA-Z0-9.-]+ 匹配一个 @ 符号,后面跟着一个或多个字母、数字、点、减号。最后的[a-zA-Z]{2,} 匹配任意两个或以上的字母。这个正则表达式可以匹配类似 john.doe@gmail.com 这样的邮箱地址。
5. 总结
Linux C 语言提供了内置的正则表达式库来帮助处理字符串。通过使用正则表达式,我们可以更加优雅地处理字符串,进行搜索、替换等操作。在本文中,我们首先介绍了正则表达式的基本知识,包括正则表达式的语法和实例。然后,我们介绍了 Linux C 中的正则表达式库 regex.h,以及常用的正则表达式匹配函数。最后,我们通过示例代码演示了如何使用正则表达式匹配 IP 地址、手机号码、邮箱地址。希望读者在学习本文后,能够更好地应用正则表达式来处理字符串。