gpt4 book ai didi

regex - 为什么不是//和m//完全同义?

转载 作者:行者123 更新时间:2023-12-03 20:21:15 25 4
gpt4 key购买 nike

从下面的示例中,我看到/ /m/ /不是完全同义的,这与我的预期相反。我认为使用m/ /而不是/ /的唯一原因是它允许使用不同的定界符(例如m{ })。它们为什么不同,为什么我要相对于其他使用?

我正在目录中搜索CSV文件。首先,我搜索了以csv结尾的文件,因此(从Perl 6 REPL中看到的所有代码都显示):

> my @csv_files = dir( test => / csv $ /  );
["SampleSheet.csv".IO]

但是最近出现了一个以 Csv结尾的文件。所以我试着不区分大小写地匹配:
> my @csv_files = dir( test => m:i/ csv $ / );
Use of uninitialized value of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block <unit> at <unknown file> line 1

我发现可以通过在匹配表达式周围放置一个块来解决此问题:
> my @csv_files = dir( test => { m:i/ csv $ / } );
["SampleSheet.csv".IO]

但是,如果我在原始表达式周围使用了一个块,则它与裸 / /不匹配,但与 m/ /匹配:
> my @csv_files = dir( test => { / csv $ / } );
[]
> my @csv_files = dir( test => { m/ csv $ / } );
["SampleSheet.csv".IO]

然后我发现,如果我在 / /中使用了不区分大小写的副词,它确实可以工作:
> my @csv_files = dir( test => /:i csv $ / );
["SampleSheet.csv".IO]

无论如何, / /m/ /的行为显然不同,我还不清楚为什么。

最佳答案

/.../m/.../之间的区别

Regexes#Lexical conventions:

m/abc/;         # a regex that is immediately matched against $_ 
rx/abc/; # a Regex object
/abc/; # a Regex object


换句话说,是 /.../rx/.../是同义词,而不是 /.../m/.../:
  • /.../rx/.../将指定的正则表达式作为 Regex 对象返回,而目前尚未与任何对象匹配。
  • m/.../立即将指定的正则表达式与变量$_(所谓的“topic”)中存储的字符串匹配,并以 Match 对象或Nil的形式返回结果(如果不匹配)。

  • 示范:

    $_ = "Foo 123";

    say m/\d+/; # 「123」
    say m/\d+/.^name; # Match

    say /\d+/; # /\d+/
    say /\d+/.^name; # Regex

    有关您的代码的说明和注释

    应用正则表达式修饰符

    but recently a file ending in Csv showed up. So I tried matching case insensitively

     my @csv_files = dir( test => m:i/ csv $ / );
    Use of uninitialized value of type Any in string context.
    Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
    in block <unit> at <unknown file> line 1


    该代码立即将正则表达式与未初始化的调用范围的主题 $_匹配。这涉及将其转换为字符串(这会导致警告 Use of uninitialized value of type Any in string context),并由于没有匹配项而返回 Nil。因此,您实际上是将该函数称为 dir( test => Nil )

    要使其工作,请使用 rx或在正则表达式中应用 :i副词:

    my @csv_files = dir( test => rx:i/ csv $ / );

    my @csv_files = dir( test => / :i csv $ / );

    块作为智能匹配器

    I found that I could fix this by putting a block around the matching expression:

    > my @csv_files = dir( test => { m:i/ csv $ / } );


    那也行。这里发生的是:
  • { ... }创建一个带有单个参数的块(可在该块内部以$_的形式使用)。
  • 块中的m:i/ ... /$_匹配,并返回Match
  • 因为m:i/.../是块中的最后一条语句,所以它的Match成为该块的返回值。
  • test函数的dir副词可以接受任何智能匹配器,不仅包括Regex对象,而且还包括Block对象(请参见smart-match operator ~~ 的文档)。


  • 使用 Regex作为 Bool

    However, if I had used a block around the original expression it doesn't match with the bare / /, but it does with m/ /:

    > my @csv_files = dir( test => { / csv $ / } );
    []


    当块用作智能匹配器时,首先调用它,然后将其返回值强制转换为 Bool: True表示它已匹配,而 False表示未匹配。

    在这种情况下,您的块始终会返回一个 Regex对象。

    将正则表达式对象强制转换为 bool 值,立即将其与当前 $_匹配,如果正则表达式匹配,则返回 True;如果不匹配,则返回False:

    say /\d+/.Bool;  # False

    $_ = "123";
    say /\d+/.Bool; # True

    因此,在您的代码中,正则表达式最终会根据 $_而不是文件名反复进行检查:

    $_ = "abc";
    .say for dir test => { / \d+ / } # Returns no filenames

    $_ = "abc 123";
    .say for dir test => { / \d+ / } # Returns all filenames

    按文件扩展名过滤文件

    I am searching for CSV files in a directory. At first I searched for files ending in csv, thus (all code shown as seen from the Perl 6 REPL):

    > my @csv_files = dir( test => / csv $ /  );


    这不只是查找具有CSV扩展名的文件,而是 以三个字母cvs结尾的所有文件,包括 foobarcsvfoobar.xcsv之类的文件。
    如果只需要CSV文件,则有两种更好的编写方法:

    my @csv-files = dir test => / ".csv" $ /;

    my @csv-files = dir.grep: *.extension eq "csv"

    或不区分大小写的版本:

    my @csv-files = dir test => / :i ".csv" $ /;

    my @csv-files = dir.grep: *.extension.lc eq "csv"

    关于regex - 为什么不是//和m//完全同义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45327007/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com