2015-08-31 84 views
0

我想从我的文件中存在的字符串中删除单词Z或ZN和LVT,但我无法得到它。有人可以检查我的代码。使用Perl从字符串中删除匹配的单词

输入

abchsfk/jshflka/ZN      (cellLVT) 
asjkfsa/sfklfkshfsf/Z     (mobLVT) 
asjhfdjkfd/sjfdskjfhdk/hsakfshf/Z  (celLVT) 
asjhdjs/jhskjds/ZN      (abcLVT) 
shdsjk/jhskd/ZN       (xyzLVT) 

输出

abchsfk/jshflka      cell 
asjkfsa/sfklfkshfsf     mob 
asjhfdjkfd/sjfdskjfhdk/hsakfshf  cel 
asjhdjs/jhskjds      abc 
shdsjk/jhskd      xyz 

CODE:

 if ($line =~ /LVT/ && ($line =~ /ZN/ || $line =~ /Z/))   

     #### matches the words LVT and (Z or ZN) 

     { 
      my @names = split//, $line;  ##### splits the line 


       $names[2] =~ s/\/Z|/ZN//g;  #### remove Z or ZN 
       $names[3] =~ s/\(|LVT\)//g ; #### remove LVT & braces 

       print OUT " $names[2] $names[3] \n"; #### print 

     } 
+1

为什么不'$线=〜S/\/ZN | LVT //克;' – sln

+0

@sln?谢谢。我想要一起移除“/ Z”和“/ ZN”,而不是仅移除Z或ZN。我也想去掉大括号。所以我试图先将它拆分,然后尝试逐个删除它。 – SKG

+0

@sln。我从你提出的想法中尝试了这种方式。它为我工作。 '$ line =〜s/\/ZN?| \(| LVT \)// g;' – SKG

回答

2

的问题是匹配的顺序为:(!第二反斜杠丢失在代码中)s/\/Z|\/ZN//g。您应该首先匹配较长的字符串,否则Z将匹配并且N不会被删除。

甚至还有更简单的方法,但:只需使用\/ZN?

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

while (my $line = <DATA>) { 
    if ($line =~ /LVT/ && $line =~ /ZN?/) { 

     my @names = split ' ', $line; 
     $names[0] =~ s/\/ZN?//g; 
     $names[1] =~ s/\(|LVT\)//g; 
     print "$names[0] $names[1]\n"; 
    } 
} 
__DATA__ 
abchsfk/jshflka/ZN      (cellLVT) 
asjkfsa/sfklfkshfsf/Z     (mobLVT) 
asjhfdjkfd/sjfdskjfhdk/hsakfshf/Z  (celLVT) 
asjhdjs/jhskjds/ZN      (abcLVT) 
shdsjk/jhskd/ZN       (xyzLVT) 
+0

感谢您的解释。它真的有帮助 – SKG

+0

我还有一个问题要问这个。在我的输出中。一些线路被重复。我想对它们进行分类并仅打印一次。我可以使用排序功能吗?这里是我想要的 'while(my $ line = ){if($ line =〜/ zN?/){' my @names = split'', $线; $ names [0] =〜s/\/ZN?// g; $ names [1] =〜s/\(| LVT \)// g; my @line_out =“$ names [0] $ names [1]”; $ lvt_out = sort :: $ line_out(); print“$ lvt_out \ n”; }' – SKG

+2

@SKG:你应该在一个新的问题中提出一个新的问题。 – choroba