我想在字符串末尾匹配Internet.
或Internet
。
我可以写:
$str =~ m/Internet\.|Internet$/
有没有一种方法可以写regex
而不必重复Internet
?
答案 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
此外,如果要存储在组中,请使用括号。