5

我想做的是允许程序根据遇到的文本定义字符类。但是,<[]> 会按字面意思接受字符,以下会产生错误:

my $all1Line = slurp "htmlFile";
my @a = ($all1Line ~~ m:g/ (\" || \') ~ $0 {} :my $marker = $0; http <-[ $marker ]>*? page <-[ $marker ]>*? /); # error: $marker is taken literally as $ m a r k e r

我想匹配格式为“ https://foo?page=0?ssl=1 ”或“http ... page ...”的所有链接

4

1 回答 1

6

根据您的示例代码和文本,我不完全确定您的源数据是什么样的,所以我无法提供更详细的信息。也就是说,根据如何从匹配的早期部分匹配字符,最简单的方法是使用数组匹配:

my $input = "(abc)aaaaaa(def)ddee(ghi)gihgih(jkl)mnmnoo";

my @output = $input ~~ m:g/
    :my @valid;                # initialize variable in regex scope
    '(' ~ ')'  $<valid>=(.*?)  # capture initial text
    { @valid = $<valid>.comb } # split the text into characters
    $<text>=(@valid+)          # capture text, so long as it contains the characters
/;

say @output;
.say for @output.map(*<text>.Str);

其中的输出是

[「(abc)aaaaaa」
 valid => 「abc」
 text => 「aaaaaa」 「(def)ddee」
 valid => 「def」
 text => 「ddee」 「(ghi)gihgih」
 valid => 「ghi」
 text => 「gihgih」]
aaaaaa
ddee
gihgih

或者,您可以将整个字符类定义存储在一个变量中并将该变量引用为<$marker-char-class>,或者如果您想避免这种情况,您可以将其全部内联定义为代码以解释为带有 的正则表达式<{ '<[' ~ $marker ~ ']>' }>。请注意,这两种方法都存在相同的问题:您正在从正则表达式语法构造字符类,这可能需要转义字符或特定的顺序,因此绝对不是最佳的。

如果这是您经常做的事情而不是非常临时的事情,您也可以定义自己的正则表达式方法令牌,但这可能非常过分,并且可以更好地作为自己的问题。

于 2019-10-26T04:32:12.250 回答