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