4

我正在阅读有关如何从网页中解析 URL 的问题,并且对提供此解决方案的已接受答案有疑问:

((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)

该解决方案由csmba提供,他将其归功于regexlib.com。唷。学分完成。

我认为这是一个相当幼稚的正则表达式,但它是构建更好的东西的一个很好的起点。但是,我的问题是:

有什么意义{1}?它的意思是“完全是以前的分组之一”,对吧?这不是正则表达式中分组的默认行为吗?如果{1}删除了,表达式会以任何方式改变吗?

如果我从同事那里看到这一点,我会指出他或她的错误,但当我写这篇文章时,响应被评为 6 分,而 regexlib.com 上的表达式被评为 4 分,5 分。所以也许我遗漏了什么?

4

4 回答 4

3

@Rob 我不同意。为了强制执行您的要求,我认为您需要使用消极的后视,这是可能的,但肯定与使用 {1} 无关。正则表达式的两个版本都没有解决该特定问题。

让代码说话:

tibook 0 /home/jj33/swap > cat text
Text this is http://example.com text this is
Text this is http://http://example.com text this is
tibook 0 /home/jj33/swap > cat p
#!/usr/bin/perl

my $re1 = '((mailto\:|(news|(ht|f)tp(s?))\://){1}\S+)';
my $re2 = '((mailto\:|(news|(ht|f)tp(s?))\://)\S+)';

while (<>) {
  print "Evaluating: $_";
  print "re1 saw \$1 = $1\n" if (/$re1/);
  print "re2 saw \$1 = $1\n" if (/$re2/);
}
tibook 0 /home/jj33/swap > cat text | perl p
Evaluating: Text this is http://example.com text this is
re1 saw $1 = http://example.com
re2 saw $1 = http://example.com
Evaluating: Text this is http://http://example.com text this is
re1 saw $1 = http://http://example.com
re2 saw $1 = http://http://example.com
tibook 0 /home/jj33/swap >

因此,如果两个版本之间存在差异,那么它似乎不是您建议的版本。

于 2008-08-17T02:46:42.740 回答
2

我认为 {1} 在该正则表达式中没有任何有效功能。

(**mailto:|(news|(ht|f)tp(s?)):// ){1}**

您应该将其阅读为:“仅一次捕获括号中的内容”。但是我们并不真正关心捕获它以供以后使用,例如替换中的 1 美元。所以毫无意义。

于 2008-08-17T02:58:18.083 回答
1

我不认为它有任何目的。但是因为 RegEx 几乎不可能理解/分解,所以人们很少指出错误。这可能就是为什么没有其他人指出它的原因。

于 2008-08-17T02:18:06.773 回答
1

@Jeff Atwood,您的解释有点偏离- {1} 表示仅匹配一次,但对“捕获”没有影响-由于括号而发生捕获-大括号仅指定模式必须匹配的次数来源 - 一次,正如你所说。

我同意@Marius,即使他的回答有点简洁并且可能会显得轻率。正则表达式很难,如果一个人不习惯使用它们,并且问题中的 {1} 并不是完全错误 - 在支持它的系统中,它确实意味着“完全匹配”。从这个意义上说,它并没有真正做任何事情。

不幸的是,与现在已删除的帖子相反,它不会阻止正则表达式匹配http://http://example.org,因为末尾的 \S+ 将匹配一个或多个非空白字符,包括http://example.orgin http://http://example.org(使用 Python 2.5 验证,以防万一我正则表达式读取已关闭)。所以,给出的正则表达式并不是最好的。我不是 URL 专家,但可能有必要(但不足以)在第一个之后限制“:”和“//”的出现以确保良好的 URL。

于 2008-08-17T02:56:56.337 回答