我试图将文件名中的三个字母与 1000Genomes 项目匹配,并且只匹配三个字母,来自像ethnicity_lists/PEL.txt
我应该只得到PEL
. 字符串的其余部分无关紧要。
my $p1-label = @populations[$p1-index].match(/^ethnicity_lists\/(<[A..Y]>)**3\.txt$/);
Run Code Online (Sandbox Code Playgroud)
问题是$p1-label
包括捕获组之外的整个字符串。
我已经把括号放在了<[A..Y]>
强调我只想要那个组。
浏览https://docs.perl6.org/routine/match
我尝试尽可能具体以防止任何可能的错误,这就是我包含整个字符串的原因。
如果我进行 Perl5 风格的匹配:
if @populations[$p1-index] ~~ /^ethnicity_lists\/(<[A..Y]>)**3\.txt$/ {
put $0.join(''); # strange that this outputs an array instead of a string
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试了该match
方法的所有副词,但没有一个完成必要的工作。
如何将match
方法仅限于正则表达式中的捕获组?
match 方法返回一个 Match 对象,其中包含有关您的匹配的所有信息。如果你这样做:
my $p1-label = @populations[$p1-index].match(/^ethnicity_lists\/(<[A..Y]>)**3\.txt$/);
say $p1-label;
Run Code Online (Sandbox Code Playgroud)
您会看到它包含 3 个标记为0
因为括号外提到的 **3 的项目:
?ethnicity_lists/PEL.txt?
0 => ?P?
0 => ?E?
0 => ?L?
Run Code Online (Sandbox Code Playgroud)
获取 Match 对象的 Str 表示可为您提供完整的匹配。但是你也可以要求它的[0]
索引。
say say $p1-label[0]'
[?P? ?E? ?L?]
Run Code Online (Sandbox Code Playgroud)
让我们修复正则表达式以将量词放在括号中,看看我们得到了什么。
my $p1-label = @populations[$p1-index].match(/^ethnicity_lists\/(<[A..Y]>**3)\.txt$/);
say $p1-label;
?ethnicity_lists/PEL.txt?
0 => ?PEL?
Run Code Online (Sandbox Code Playgroud)
看起来更好。现在,如果你只想要PEL
一点,你有两个选择。您可以获取匹配中第一项的 Str 表示:
my $p1-label = @populations[$p1-index].match(/^ethnicity_lists\/(<[A..Y]>**3)\.txt$/)[0].Str;
say $p1-label;
PEL
Run Code Online (Sandbox Code Playgroud)
请注意,如果我不将其强制为字符串,我将获得子匹配的匹配对象。(这可能有用,但不是您需要的)。
或者您可以使用零宽度断言并完全跳过捕获:
my $p1-label = @populations[$p1-index].match(/<?after ^ethnicity_lists\/><[A..Y]>**3<?before \.txt$>/).Str;
say $p1-label;
PEL
Run Code Online (Sandbox Code Playgroud)
在这里,我们匹配出现在表达式之后^ethnicity_lists\/
和之前的 3 个大写字母,\.txt$
但它们不包含在匹配本身中。
或者正如@raiph 所指出的,您可以使用双重捕获来告诉系统这是您唯一想要的:
my $p1-label = @populations[$p1-index].match(/^ethnicity_lists\/<(<[A..Y]>**3)>\.txt$/)[0].Str;
say $p1-label;
PEL
Run Code Online (Sandbox Code Playgroud)
这最后一个可能是最好的。
希望有帮助。
它输出一个数组,因为捕获组匹配多次。您需要将量词放入组内:
/^ethnicity_lists\/(<[A..Y]>**3)\.txt$/;
say $0; # PEL
Run Code Online (Sandbox Code Playgroud)
@Holli 的回答提出了一个关键点,@Scimon 深入探讨了为什么你得到了你得到的结果,但是......
如果你加倍强调你想要的部分<( ... )>
而不是仅仅( ... )
让那部分成为整体捕获对象。
如果你使用put
而不是say
你得到机器友好的字符串化(与 相同.Str
,在这种情况下PEL
)而不是人类友好的字符串化(与 相同.gist
,所以在这种情况下它会是?PEL?
):
put 'fooPELbar' ~~ / foo ( ... ) bar /; # fooPELbar
put 'fooPELbar' ~~ / foo <( ... )> bar /; # PEL
Run Code Online (Sandbox Code Playgroud)