从下面的例子中,我看到/ /并且m/ /不完全是同义词,与我的预期相反.我认为唯一的理由使用m/ /,而不是/ /是,它允许使用不同的分隔符(如m{ }).为什么他们不同,为什么我要使用一个与另一个?
我在目录中搜索CSV文件.起初我搜索了以文件结尾的文件csv(所有代码显示为从Perl 6 REPL中看到的):
> my @csv_files = dir( test => / csv $ / );
["SampleSheet.csv".IO]
Run Code Online (Sandbox Code Playgroud)
但最近出现了一个文件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
Run Code Online (Sandbox Code Playgroud)
我发现我可以通过在匹配表达式周围放置一个块来解决这个问题:
> my @csv_files = dir( test => { m:i/ csv $ / } );
["SampleSheet.csv".IO]
Run Code Online (Sandbox Code Playgroud)
但是,如果我在原始表达式周围使用了一个块,它与裸片不匹配/ /,但它与m/ /:
> my @csv_files = dir( test => { / csv $ / } );
[]
> my @csv_files = dir( test => { m/ csv $ / } );
["SampleSheet.csv".IO]
Run Code Online (Sandbox Code Playgroud)
然后我发现如果我在里面使用不区分大小写的副词/ /,它确实有效:
> my @csv_files = dir( test => /:i csv $ / );
["SampleSheet.csv".IO]
Run Code Online (Sandbox Code Playgroud)
无论如何,/ /并且m/ /显然表现不同,我还不清楚为什么.
/.../和之间的区别m/.../来自Regexes#词汇约定:
Run Code Online (Sandbox Code Playgroud)m/abc/; # a regex that is immediately matched against $_ rx/abc/; # a Regex object /abc/; # a Regex object
换句话说,它是/.../和rx/.../是同义词,不/.../和m/.../:
/.../并将rx/.../指定的正则表达式作为Regex对象返回,而不是将其与任何内容相匹配.m/.../立即对匹配一个储存在变量中的字符串指定的正则表达式$_(即所谓的"主题"),并返回结果作为Match对象,或者Nil如果没有匹配.示范:
$_ = "Foo 123";
say m/\d+/; # ?123?
say m/\d+/.^name; # Match
say /\d+/; # /\d+/
say /\d+/.^name; # Regex
Run Code Online (Sandbox Code Playgroud)
但最近以Csv结尾的文件出现了.所以我尝试不敏感地匹配大小写
Run Code Online (Sandbox Code Playgroud)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 $ / );
Run Code Online (Sandbox Code Playgroud)
my @csv_files = dir( test => / :i csv $ / );
Run Code Online (Sandbox Code Playgroud)
我发现我可以通过在匹配表达式周围放置一个块来解决这个问题:
Run Code Online (Sandbox Code Playgroud)> my @csv_files = dir( test => { m:i/ csv $ / } );
这也有效.这里发生的是:
{ ... }创建一个采用单个参数的块(可$_在块内部使用).m:i/ ... /系统中的块对匹配$_,并返回Match.m:i/.../是块中的最后一个语句,所以它Match成为块的返回值.test副词dir接受任何智能匹配器,它不仅包括Regex对象,还包括Block对象(请参阅智能匹配运算符~~的文档).Regex作为Bool但是,如果我在原始表达式周围使用了一个块,它与裸/ /不匹配,但它与m//相符:
Run Code Online (Sandbox Code Playgroud)> my @csv_files = dir( test => { / csv $ / } ); []
当一个块被用作智能匹配器时,它首先被调用,然后它的返回值被强制转换为Bool:True表示它匹配,False意味着它没有.
在这种情况下,您的块始终会返回一个Regex对象.
将正则表达式对象强制转换为布尔值,立即将其与当前匹配,并在正则表达式匹配时$_返回,True如果不匹配则返回"False":
say /\d+/.Bool; # False
$_ = "123";
say /\d+/.Bool; # True
Run Code Online (Sandbox Code Playgroud)
因此,在您的代码中,正则表达式最终会被反复检查$_,而不是针对文件名:
$_ = "abc";
.say for dir test => { / \d+ / } # Returns no filenames
$_ = "abc 123";
.say for dir test => { / \d+ / } # Returns all filenames
Run Code Online (Sandbox Code Playgroud)
我在目录中搜索CSV文件.起初我搜索以csv结尾的文件,因此(所有代码显示为从Perl 6 REPL中看到的):
Run Code Online (Sandbox Code Playgroud)> my @csv_files = dir( test => / csv $ / );
这不只是查找具有CSV扩展名的文件,而是查找以三个字母结尾的所有文件cvs,包括foobarcsv或等foobar.xcsv.
如果您只想要CSV文件,可以使用以下两种方法编写它:
my @csv-files = dir test => / ".csv" $ /;
Run Code Online (Sandbox Code Playgroud)
my @csv-files = dir.grep: *.extension eq "csv"
Run Code Online (Sandbox Code Playgroud)
或不区分大小写的版本:
my @csv-files = dir test => / :i ".csv" $ /;
Run Code Online (Sandbox Code Playgroud)
my @csv-files = dir.grep: *.extension.lc eq "csv"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
198 次 |
| 最近记录: |