2011-12-27 54 views
10

当我运行这段代码,我得到“没有”打印出来:的Perl写一个“内存文件”玩技巧与模式匹配

my $memory_file; 
my $fh; 
open ($fh, '>', \$memory_file); 
print $fh "abc"; 
if($memory_file =~ m/^.*$/) 
{ print "yes\n" } 
else 
{ print "no\n" } 

如果我打印出来$memory_file,内容确实是​​。

如果我将模式更改为.*(否^$),它按预期工作。

如果在比赛开始前我把$memory_file = "abc"放在了一行,我会打印出“yes”(正如原来的预期)。

这到底是怎么回事?

(这是Perl的5.14.1)

更新:PerlMonks一些更多的讨论。它看起来像一个错误,我会记录它。

更新2:精细Perl开发人员有固定的这个错误:https://rt.perl.org/rt3//Public/Bug/Display.html?id=108398

+1

这看起来像一个bug:http://perldoc.perl.org/perlbug.html('perldoc perlbug') – toolic 2011-12-28 01:52:13

回答

4

这是行尾字符混淆了事情。虽然定期作业:

my $str = "abc"; 
print "Works" if $str =~ /^.*$/; 

...问题中的代码没有。这个正则表达式应该匹配任何字符串,因为它也匹配空字符串。即使未定义的值也会匹配(尽管它会导致警告)。另外,^.*确实匹配。

,唯一合理的解释是,由于某种原因,无论执行检查,以匹配字符串的结束,它没有找到它。字符串的末尾丢失。

奇怪的是,与\z作品代替$。但不是\Z

添加一个新行也有效。这是有道理的,因为添加一个换行符意味着字符串的末尾也被添加,在非多行正则表达式意义上。

我不知道为什么发生这种情况的内部运作,但我怀疑使用“转让”的这种特殊形式的时候,结束的字符串的标记永远置于字符串。一种“原始”分配,它混淆了正则表达式中字符串结尾的检查。

感觉就像一个错误。也许这个特殊的功能还没有得到妥善的维护。

+0

: 使用此模块“内存中的文件”工作另一个数据点,将''abc \ n“'打印到mem文件并与'^。* \ n $'匹配也失败了(但是'normal'字符串成功了)。正如其他地方所指出的,将''abc \ n“'与'^。* $'匹配成功。 – jwd 2011-12-28 00:49:50

0

好了,我的第一反应是说,在内存中的文件不作为一样的物理文件。尝试更改print $fh "abc";print $fh "abc\n";以查看您的输入是否成为一条线。

我的另一个直觉是,你的文件实际上并没有写入之前,你读它。同花顺$|++;

所以你的缓冲区,尝试:

my $memory_file; 
my $fh; 
open ($fh, '>', \$memory_file); 
print $fh "abc"; 
$|++; 
if($memory_file =~ m/^.*$/) 
{ print "yes\n" } 
else 
{ print "no\n" } 
+1

我觉得'$ | ++'更像是一个配置设置,应该尽早设置,而不是被视为触发冲洗的方式。 – 2011-12-27 22:37:45

+0

@PlatinumAzure说什么。除此之外,运行您提供的代码还会在我的系统上打印“否”。你有什么不同吗? – jwd 2011-12-28 00:19:50

+3

'$ | = 1;'自动​​刷新标准输出。 (Tehcnically,当前'select'ed句柄。)你需要'$ fh-> autoflush(1);'而不是。 – ikegami 2011-12-28 01:07:26

2

我认为问题是换行和 $锚。它检查换行符后面的字符串,而你的字符串没有。

编辑

查看其他答案这个问题的详细解释,因为我的是不正确的。但我会给出两个选项来解决这个问题:

  • 写“ABC \ n”来你的文件,并用绳子与\z$
  • 检查结束检查。
+0

这是不正确的。 '$匹配行的末尾(或末尾的换行符)'请参阅[perlre](http://perldoc.perl.org/perlre.html#Metacharacters)。 – TLP 2011-12-27 23:05:47

+0

即使它是正确的,'。*'匹配任何*字符串,因为它也匹配空字符串。 – TLP 2011-12-27 23:06:16

+0

@TLP:你说得对。我会删除我的答案以避免混淆。 – Birei 2011-12-28 08:22:55

2

只是使用一个辅助变量。

#$| = 1; # AutoFlush 

my $memory_file; 
open (my $fh, '>>', \$memory_file) or die $!; 
print $fh "abc"; 

my $buff = $memory_file; 

if($buff =~ m/^abc$/){ # or m/^.*$/ 
    print "yes\n"; 
}else{ 
    print "no\n"; 
} 
+0

这也可以不串联:'my $ buff = $ memory_file'。 – TLP 2011-12-28 00:01:42

+0

到底!只需使用一个辅助变量。 – killzone 2011-12-28 00:09:53

+0

将它存储到一个临时变量确实有效,所以非常感谢。你对这种行为有任何方便的解释吗? – jwd 2011-12-28 00:20:32