4

我有这个:

use constant JAR_FILE => qr/\.jar$/;

my @dir_list = ...;
my @jar_list;
find ( sub {
    return unless -f;
    return unless JAR_FILE;   #THIS IS THE TROUBLED LINE
    push @jar_list, $File::Find::name;
    }, @dir_list;

say join ": ", @jar_list;

这会打印出所有的文件@dir_list——jar 文件和非 jar 文件;

然而,这:

use constant JAR_FILE => qr/\.jar$/;

my @dir_list = ...;
my @jar_list;
find ( sub {
    return unless -f;
    return unless $_ =~ JAR_FILE;  #Now explicitly do the comparison 
    push @jar_list, $File::Find::name;
    }, @dir_list;

say join ": ", @jar_list;

只打印出 jar 文件。

这也只打印出 jar 文件:

# use constant JAR_FILE => qr/\.jar$/;

my @dir_list = ...;
my @jar_list;
find ( sub {
    return unless -f;
    return unless /\.jar$/;  #Use regex and not constant regex. 
    push @jar_list, $File::Find::name;
    }, @dir_list;

say join ": ", @jar_list;

为什么第一个return unless JAR_FILE;不起作用,return unless $_ =~ JARFILE;return unless /\.jar$/;两者都起作用?

4

2 回答 2

7

它与常数无关。

>perl -wE"$_ = '.txt'; say qr/\.jar$/ ?1:0;"
1

>perl -wE"$_ = '.txt'; say /\.jar$/ ?1:0;"
0

>perl -wE"$_ = '.txt'; say $_ =~ qr/\.jar$/ ?1:0;"
0

qr//编译正则表达式模式并将其返回,而匹配运算符 ( m//aka //) 执行正则表达式匹配。

由于qr//总是返回真值(编译的正则表达式),return unless qr/\.jar$/;因此永远不会返回。

=~ qr/\.jar$/之所以有效,是因为=~如果 RHS 操作数不是匹配运算符 ( m//)、替换运算符 ( s///) 或翻译运算符 ( ),则意味着匹配运算符tr///

my $re = qr/\.jar$/;
$_ =~ $re

简称

my $re = qr/\.jar$/;
$_ =~ /$re/

这是久违的

my $re = qr/\.jar$/;
/$re/

如果同时省略 the//和 the =~,则不再有匹配运算符。

于 2013-05-01T14:39:31.330 回答
1

问题是,qr//除非你告诉它,否则它不会与任何东西相匹配。
(这是唯一的原因qr//甚至是语言的一部分)

my $match_jar = qr/\.jar$/;

$_ = undef;

print $match_jar, "\n" if $match_jar; # always prints

for( qw' matches.jar doesnt.txt ' ){
  print $_, "\n" if $_ =~ $match_jar; # only prints "matches.jar"

  # here is the reason qr// exists
  my $bool = /\.jar$/;
  print $bool, "\n"; # prints 1 or ''
}
(?^:\.jar$)
匹配.jar
1


那么如何不使用常量,而是自己定义“常量”。
(注意:常量实际上只是创建可内联的子例程,Perl 并没有真正的常量。)

sub MATCH_JAR_FILE(_){ $_[0] =~ /\.jar$/ } # 5.10.0 or later

...
  # test against $_
  return unless MATCH_JAR_FILE;
...
  return unless MATCH_JAR_FILE($var);
...

5.10之前,您将不得不以不同的方式编写它。

sub MATCH_JAR_FILE(;$){
  @_ = $_ unless @_; # doesn't get lexical $_
  $_[0] =~ /\.jar$/
}

请注意,您必须将出现的任何替换... =~ JAR_FILE;MATCH_JAR_FILE(...)


如果您不介意使用CPAN中的模块,您可以使用Want。然后,您将有另一种方法来使用子例程。

use Want 'want';

sub JAR_FILE(_){
  return $_[0] =~ /\.jar$/ if want 'BOOL';
  return qr/\.jar$/
}

...
  # test against $_
  return unless JAR_FILE; # bool
...
  return unless $var =~ JAR_FILE;
...
  return unless JAR_FILE($var); # bool
...

5.10之前,您可能会以完全不同的方式编写它。

use Want 'want';

sub JAR_FILE(){
  return /\.jar$/ if want 'BOOL';
  return qr/\.jar$/
}

...
  # test against $_
  return unless JAR_FILE; # bool
...
  return unless $var =~ JAR_FILE;
...
  # return unless JAR_FILE($var); # doesn't work
...
于 2013-05-02T16:48:22.487 回答