2016-04-26 81 views
2

我有这个数组。为什么perl正则表达式不起作用?

my @input = ("He walk+V3SG very fast.", "He study+V3SG hard."); 

我想用'walk + V3SG'和'study + V3SG'来代替'走路'和'学习'。

下面是我写的脚本。我认为这应该工作,但由于某种原因,它不工作。

foreach my $sent(@input){ 
    if ($sent =~ m/\Q+V3SG/){ 
     if ($sent =~ m/\Q[dlr]y+V3SG/){ 
      $sent =~ s/\Q[dlr]y+V3SG/ies/g; 
     } 
     if ($sent =~ m/\Q[s|x|sh|ch|o]+V3SG/){ 
      $sent =~ s/\Q[s|x|sh|ch|o]+V3SG/es/g; 
     } 
     else {$sent =~ s/\Q+V3SG/s/g} 
    } 
} 

foreach my $sent(@input){ 
    print $sent; 
    print "\n"; 
} 

谁能告诉我这个脚本有什么问题吗?

回答

2

\Q使正则表达式的其余部分符合字面意思[dlr]y+V3SG。移动它使字符类正常工作:

s/[dlr]\Qy+V3SG/ies/g 

或只是逃避+

s/[dlr]y\+V3SG/ies/g 

此更改后,你得到的,例如:

He stuies hard. 

要确保第一个字母被保留,您可以使用捕获或\K(自5.10):

s/[dlr]\K\Qy+V3SG/ies/g 

对于第二个正则表达式,你使用了错误的括号:

s/(s|x|sh|ch|o)\Q+V3SG/$1es/g 
+1

此外,他们不应该使用if/ELSIF /别的都没有。这句话可以包含所有三种形式。 – ikegami

+0

非常感谢你(; –

0

你应该保持\Q之前只是文字。你把它放在整个正则表达式之前,所以整个正则表达式被认为是字面的,并没有被解释。

第二件事你应该明智地用\K来代替。把它放在你不想替换的部分之后。例如:s/[dlr]\Ky\Q+V3SG/ies/g使得studystudies并且它不会从结果中删除dlr

第三件事[s|x|sh|ch|o]不会做你的想法。它将匹配s,x,h,|,c,o中的任何字符。正确的应该是(?:s|x|sh|ch|o)(?:...)用于非捕获组。

最后,这应该不是一个if/elsif/else。这句话可以包含所有三种形式。

总评:它给我们:

#!/usr/bin/perl 
use strict; 
use warnings; 

my @input = ("He walk+V3SG very fast.", "He study+V3SG hard.","He crush+V3SG hard."); 

foreach (@input){ 
    if (m/\Q+V3SG/){ 
     s/[dlr]\Ky\Q+V3SG/ies/g; 
     s/(?:s|x|sh|ch|o)\K\Q+V3SG/es/g; 
     s/\Q+V3SG/s/g; 
    } 
} 

foreach my $sent(@input){ 
    print $sent; 
    print "\n"; 
} 
+0

非常感谢你! –

相关问题