这个正则表达式匹配URL有什么问题?
我在设置正则表达式来匹配使用C中的regex.h库的URL时遇到了一些困难。我有一个正在工作的IP正则表达式,我希望将其转换为匹配一个简单的字符串,如www.alphanumerictext12.com|edu|org
。正则表达式定义本身的语法有些问题。这个正则表达式匹配URL有什么问题?
下面是工作IPREGEX代码和我尝试的URL正则表达式。
#define IPEXPR "([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})"
#define URLEXPR "(www)\\.((?:[a-z][a-z]*[0-9]+[a-z0-9]*))\\.(com|edu|org)"
regex_t regex;
if(regcomp(®ex, IPEXPR, REG_EXTENDED) != 0)
return 0;
if(regexec(®ex, inputURL, 0, NULL, 0) != 0)
return 0;
尝试:
"www\\.[a-z]+[a-z0-9]*\\.(com|edu|org)"
我删除了[0-9]+
与[a-z]+
更换[a-z][a-z]*
。
我希望这是不区分大小写的,下面会更好一些吗? :“www \\。[a-zA-Z] + [a-zA-Z0-9] * \\。(com | edu | org)” – 2009-11-16 15:13:54
您可以这样做,但不会允许.COM '或'.eDu'作为顶级域名。你可以通过在你的正则表达式前面添加'(?i)'标志来启用不区分大小写的匹配:'“(?i)www \\。[az] + [a-z0-9] * \\。 edu | org)“'假设你正在使用的正则表达式库支持'(?i)'。 – 2009-11-16 15:53:19
我在Ubuntu上使用c中的regex.h。我会给(?)一个测试。 “www \\。[az] + [a-z0-9] * \\。(com | edu | org)”正在令人愉快地工作,现在我需要添加字符 - 和_我在哪里放置他们在?我试图将它们加入,如[a-z0-9-_]但失败。我在这里观看什么关键?谢谢大家,CB – 2009-11-16 16:12:44
问题出在(?:)
,您只需要(www)\\.([a-z][a-z]*[0-9]+[a-z0-9]*)\\.(com|edu|org)
。
顺便说一下,你的内心表达说:“至少有一个字母字符,然后至少有一个数字字符,然后是任何字母数字字符”。这是你的意思吗?如果是这样,你可以缩短一点:[a-z]+[0-9]+[a-z0-9]*
。
“至少有一个字母字符,然后至少有一个数字字符,然后是任何字母数字字符”。这是你的意思吗?不,这将是一个错误。 我会给你的正则表达式尝试并报告回来,谢谢! CB – 2009-11-16 15:12:04
然后你可能更喜欢[az] + [a-z0-9] *,但要注意,域名可以以数字开头:) – 2009-11-16 15:48:30
一些人,当遇到一个问题,认为 “我知道,我将使用 正则表达式。”现在他们有 两个问题。
我的意思是:你确定正则表达式是解决问题的最好方法吗?也许你可以测试这个字符串是否是一个带有更多轻量级方法的URL?
编辑
我的电脑下面的程序,具有输出重定向到/dev/null
,打印(到stderr
)
rx time: 1.730000 lw time: 0.920000
计划清单:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <string.h>
#include <time.h>
int goodurl_rx(const char *buf) {
static regex_t rx;
static int done = 0;
int e;
if (!done) {
done = 1;
if ((e = regcomp(&rx, "^www\\.[a-z][a-z0-9]*\\.(com|edu|org)$", REG_EXTENDED)) != 0) {
printf("Error %d compiling regular expression.\n", e);
exit(EXIT_FAILURE);
}
}
return !regexec(&rx, buf, 0, NULL, 0);
}
int goodurl_lw(const char *buf) {
if (*buf++ != 'w') return 0;
if (*buf++ != 'w') return 0;
if (*buf++ != 'w') return 0;
if (*buf++ != '.') return 0;
if (!isalpha((unsigned char)*buf++)) return 0;
while (isalnum((unsigned char)*buf)) buf++;
if (*buf++ != '.') return 0;
if ((*buf == 'c') && (*(buf+1) == 'o') && (*(buf+2) == 'm') && (*(buf+3) == 0)) return 1;
if ((*buf == 'e') && (*(buf+1) == 'd') && (*(buf+2) == 'u') && (*(buf+3) == 0)) return 1;
if ((*buf == 'o') && (*(buf+1) == 'r') && (*(buf+2) == 'g') && (*(buf+3) == 0)) return 1;
return 0;
}
int main(void) {
clock_t t0, t1, t2;
char *buf[] = {"www.alphanumerics.com", "ww2.alphanumerics.com", "www.alphanumerics.net"};
int times;
t0 = clock();
times = 1000000;
while (times--) {
printf(" %s: %s\n", buf[0], goodurl_rx(buf[0])?"pass":"invalid");
printf(" %s: %s\n", buf[1], goodurl_rx(buf[1])?"pass":"invalid");
printf(" %s: %s\n", buf[2], goodurl_rx(buf[2])?"pass":"invalid");
};
t1 = clock();
times = 1000000;
while (times--) {
printf(" %s: %s\n", buf[0], goodurl_lw(buf[0])?"pass":"invalid");
printf(" %s: %s\n", buf[1], goodurl_lw(buf[1])?"pass":"invalid");
printf(" %s: %s\n", buf[2], goodurl_lw(buf[2])?"pass":"invalid");
} while (0);
t2 = clock();
fprintf(stderr, "rx time: %f\n", (double)(t1-t0)/CLOCKS_PER_SEC);
fprintf(stderr, "lw time: %f\n", (double)(t2-t1)/CLOCKS_PER_SEC);
return 0;
}
嗯,在这种情况下,我相信一个正则表达式是最好的答案,但是我我肯定会接受有效的建议。我以通用格式输入用户的网址:www.alphanumerics.com。你能建议一个更轻量级的方法吗? – 2009-11-16 15:20:34
pmg,几乎可以肯定这个函数是用来验证用户输入的,所以在这里真正无关紧要。 但是关于开发时间,可读性,可支持性等呢?稍做修改就需要重写你的代码,最后是自制的FSA。 – 2009-11-16 20:07:54
对于这个简单的例子,我同意正则表达式函数更容易处理。然而,有一天,当你想要“接受”co.uk和net.au时,使'ads *。*'失效,而不是'cads *。*'',...,...;也不会很好。当发生这种情况时,解析器是最好的选择,但是基于正则表达式的解决方案IMVHO倾向于使用正则表达式:更多和更尴尬。 – pmg 2009-11-16 21:26:45
您可能应该使用inet_pton()
这是一个标准的POSIX功能(替换inet_aton()
)并处理IPv4和IPv6地址格式。
我不确定我完全理解这个用法。这是否是一种更有尊严的方式来检查IP地址与我目前使用的正则表达式的有效性? (以上定义为IPEXPR) CB – 2009-11-16 15:18:16
是的,尤其是因为IPv6具有inet_pton将处理的缩写形式。这不仅仅是0-9和。 – dajobe 2009-11-16 21:17:08
好吧,我已经更新了我的正则表达式:“^(www | www1){1} \\。[a-z0-9] + [_] * [ - ] * [a-z0-9] * \\。(com | edu | org)$“这对任何我抛出的东西都非常有用,除了大小写不敏感......我的编译器不关心:”(?i)^(www | www1){1 } \\。[a-z0-9] + [_] * [ - ] * [a-z0-9] * \\。(com | edu | org)$“改善此字符串的建议?再次感谢大家,CB – 2009-11-16 16:37:41
我试着将REG_ICASE标志添加到regexec()和regcomp(),但没有运气....建议? CB – 2009-11-16 17:04:46
REG_ICASE应该可以工作。您是否尝试过regcomp(&regex,URLEXPR,REG_EXTENDED | REG_ICASE)? 而且,你能告诉我们你的目标是什么?你正在构建真正奇怪的正则表达式......它仅适用于域名的一小部分...... – 2009-11-16 18:15:54