有没有一种方法可以编写“ regex”而不重复某些部分?

时间:2020-06-25 16:46:10

标签: regex perl

我想在字符串末尾匹配Internet.Internet

我可以写:

$str =~ m/Internet\.|Internet$/

有没有一种方法可以写regex而不必重复Internet

3 个答案:

答案 0 :(得分:7)

您可以使用括号将事物分组在一起,并且管道在该组中本地工作。

这意味着您可以将ab|ac转换为a(b|c)。注意,这还会自动创建一个捕获组 1 ;如果您不想这样做,可以使用a(?:b|c)

因此,在您的情况下,您可以编写 2

$str =~ /Internet(\.|$)/

(或使用/Internet(?:\.|$)/使用非捕获组,但这似乎并不重要。)


1::这意味着匹配组的内容将进入$1(或$2等,具体取决于第多少组) ),因此使用a(b|c)会在b中得到c$1

2:我删除了m,因为它仍然是模式匹配的默认模式。

旁注::正如下面的评论者JvdV所述,根据您的用例,您还可以考虑在单词Internet之前添加单词边界。然后,它将仅匹配The Internet.(Internet.)之类的内容,而不匹配IIIIInternet.。您可以使用\b进行此操作,例如/\bInternet(\.|$)/

答案 1 :(得分:4)

首先,$与字符串的结尾不匹配(仅匹配)。您想要\z


(?:...)可以用作数学中的括号。这使我们可以按如下所示排除公共前缀:

/Internet(?:\.|\z)/

通常,我们可以使用插值或DEFINE

例如,让我们看下面的比赛,该比赛使用了长重复模式,我们不能简单地将其排除在外:

/ ^ [a-zA-Z][a-zA-Z0-9_]* (?: \. [a-zA-Z][a-zA-Z0-9_]* )* \z /x

使用插值:

my $ident = qr/[a-zA-Z][a-zA-Z0-9_]*/;
/ ^ $ident (?: \. $ident )* \z /x

使用DEFINE(更好):

/
   ^ (?&IDENT) (?: \. (?&IDENT) )* \z

   (?(DEFINE)
      (?<IDENT> [a-zA-Z][a-zA-Z0-9_]* )
   )
/x

仍然存在重复,但是我们不是重复一个复杂的模式,而是重复一个简单的单词,并且拼写错误将导致致命的错误,而不是潜在的细微行为。

答案 2 :(得分:0)

根据您的输入,它可能出现在内容的开始/中间/结尾。因此最好使用以下代码来避免出现这种情况:

$str =~ m/[Ii]nternet(\.|$)/
or
$str =~ m/Internet(\.|$)/i

此外,如果要存储在组中,请使用括号。