为什么 // 和 m// 不完全是同义词?
Why aren't // and m// exactly synonymous?
从下面的示例中,我看到 / /
和 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/.../
return 指定的正则表达式作为 Regex
对象,暂时不匹配任何东西。
m/.../
立即将指定的正则表达式与存储在变量 $_
中的字符串进行匹配(即所谓的 "topic"),结果 return 为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
),并且 returns 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/ ... /
与 $_
匹配,并且 return 是 Match
.
- 因为
m:i/.../
是块中的最后一条语句,所以它的 Match
成为块的 return 值。
dir
函数的 test
副词接受任何智能匹配器,它不仅包括 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 $ / } );
[]
当一个块被用作智能匹配器时,它首先被调用,然后它的 return 值被强制转换为 Bool
:True
表示它匹配,并且 False
表示没有。
在这种情况下,您的块总是返回一个 Regex
对象。
将正则表达式对象强制转换为布尔值,立即将其与当前 $_
匹配,如果正则表达式匹配,则 returns 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
结尾的文件,包括像 foobarcsv
或 foobar.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"
从下面的示例中,我看到 / /
和 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/.../
return 指定的正则表达式作为Regex
对象,暂时不匹配任何东西。m/.../
立即将指定的正则表达式与存储在变量$_
中的字符串进行匹配(即所谓的 "topic"),结果 return 为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
),并且 returns 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/ ... /
与$_
匹配,并且 return 是Match
. - 因为
m:i/.../
是块中的最后一条语句,所以它的Match
成为块的 return 值。 dir
函数的test
副词接受任何智能匹配器,它不仅包括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 $ / } ); []
当一个块被用作智能匹配器时,它首先被调用,然后它的 return 值被强制转换为 Bool
:True
表示它匹配,并且 False
表示没有。
在这种情况下,您的块总是返回一个 Regex
对象。
将正则表达式对象强制转换为布尔值,立即将其与当前 $_
匹配,如果正则表达式匹配,则 returns 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
结尾的文件,包括像 foobarcsv
或 foobar.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"