字符类在正则表达式中算为组吗?

2024-05-23 19:17:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我分配的一个小项目应该是从给定文本中提取网站URL。以下是其中最相关的部分:

webURLregex = re.compile(r'''(
   (https://|http://)
   [a-zA-Z0-9.%+-\\/_]+
   )''',re.VERBOSE)

这确实很好地完成了它的工作,但我注意到它在打印的URL字符串中还包括“,”和“.”所以我的第一个问题是,如何使它排除它检测到的字符串末尾的任何标点符号?

我的第二个问题是关于标题本身(最后),但似乎并没有真正影响我正在处理的这个特定程序:字符类(在本例中为[a-zA-Z0-9.%+-\/\]+)是否算作组(在本例中为组[3])

提前谢谢


Tags: 项目字符串https文本rehttpurlverbose
3条回答

反向回答: 不,字符类只是括号内文本的简写。它们提供组的方式与用括号括起来的方式不同。它们只允许正则表达式引擎选择指定的字符

关于查找逗号和点:事实上,我在这里看到了问题所在,尽管下面的内容可能仍然很有价值,所以我将保留它。本质上,您有:[a-zA-Z0-9.%+-\\/_]+字符有特殊的含义:-字符之间的所有内容都是ascii码。因此[A-a]是一个有效范围。它包括A-Z,但也包括一堆其他非A-Z的字符。如果要将-包括在范围内,则需要是最后一个字符:[a-zA-Z0-9.%+\\/_-]+应该有效


对于逗号,我实际上看不到它在正则表达式中的表示,所以我不能具体对此发表评论。它不应该被允许在url中的任何地方。但一般来说,您只需要添加更多组/更多条件

首先,将url拆分为所需的特定组: (方案):/(域)(端点)

每个部分都有不同的要求:例如,域可能需要以斜杠结尾: [a-zA-Z0-9]+\.com/应该匹配任何使用字母数字字符的域,并以.com结尾(注意\.,否则它将捕获任何后跟com/的单个字符

对于endpoint部分,您可能仍然希望允许使用特殊字符,但是如果您确信不希望url以点结尾,那么您可以做一些事情[A-Za-z0-9]注意这里没有点,另外,它的长度只有一个字符。这将改变您的正则表达式的其余部分,因此您需要考虑这一点

一些随机的想法:

  1. 如果您确信要匹配整行,请在正则表达式的末尾添加一个$,以表示该行的结尾。这里的一种可能性是您的正则表达式确实匹配文本的某些部分,但忽略了结尾的垃圾,因为您没有说要阅读整行
  2. 正则表达式变得非常复杂,它们是一种只写的代码
web_url_regex = re.compile(
  r'(http://|https://)'  # Capture the scheme name
  r'([a-zA-Z0-9.%+-\\/_])' # Everything else, apparently
)
  1. 在验证过程中不要试图详尽无遗,如上所述,URL很难验证,因为您无法确定URL是否有效。但表单非常一致,如上所述:方案、域、端点(和查询字符串)

要排除字符串末尾的某些符号,可以使用负向后查找。例如,要禁止. ,,请执行以下操作:

.*(?<![.,])$

首先要回答第二个问题,不,字符类不是一个组(除非通过将它放在括号中显式地将其变成一个组)

关于第一个问题,即如何使其排除结尾处的标点符号,下面的代码应该能回答这个问题

不过,首先,您的正则表达式有一个与匹配最终标点符号的事实不同的问题,即最后一个-似乎不是用来定义字符范围的(请参见下面的脚注,了解我为什么认为是这样),而是这样做的。为了避免这个问题,我把它移到了角色类的末尾

现在,在regexp的末尾添加了一个与最终字符匹配的字符类,该字符类与前面的字符类相同,只是它不包括.(其他标点现在已经不包括)。因此,匹配的模式不能以.结尾。上一个字符类上的+(一个或多个)现在减少为*(零个或多个)

如果出于任何原因,需要对匹配的字符集进行调整,那么仍然可以使用相同的原则:在减少的可能性集的末尾匹配单个字符,前面是更大的集合中的任意数量的字符,其中包括允许包含但不在末尾的字符

import re

webURLregex = re.compile(r'''(
   (https://|http://)
   [a-zA-Z0-9.%+\\/_-]*
   [a-zA-Z0-9%+\\/_-]
   )''',re.VERBOSE)

str = "... at http://www.google.com/. It says"

m = re.search(webURLregex, str)

if m:
    print(m.group())

产出:

http://www.google.com/

[*]第二个-似乎不打算定义字符范围的观察结果是基于这样一个事实,即如果是,那么该范围将是从056-134(八进制)开始的,这也将包括字母字符,使得a-zA-Z冗余

相关问题 更多 >