2015-06-16 42 views
0

如果文件中的单词匹配某些关键字/名称,我试图做HTML突出显示。然而,有时候关键词的一部分也存在,Perl会再次匹配它。如何在搜索和替换过程中让perl跳过某些单词

例如,我有以下关键词

  1. KY SPINE & REHAB - 当发现与它周围的方括号
  2. SPINE更换 - 发现与它周围的圆括弧
  3. REHAB更换时 - 当发现圆括号代替它周围

一旦它匹配KY SPINE & REHAB,我想要阻止它匹配SPINEREHAB

这就是我现在得到的。我不能给HTML的例子,因为我不知道如何显示HTML标记,因为这个网站翻译它,只显示文本。实际上,我试图用不同的颜色来突出显示这些关键字,这些关键字来自于它们来自哪一组。

我现在得到:

[KY (SPINE) & (REHAB)] 

我要的是:

[KY SPINE & REHAB] 

如何让我的Perl跳过的话,在做搜索和替换?

我有数百万条记录,我必须这样做,即使并行处理速度也不是那么快。所以,代码高效的建议将不胜感激。

作为更新,我有数百个关键字,任何关键字可能是另一个关键字的子集。所以对其进行硬编码是不实际的。我正在寻找解决方案,perl可以跳过方括号内的字符串,这样就不会发生进一步的替换。

+0

欢迎堆栈溢出。看看http://stackoverflow.com/editing-help并了解问题和答案的格式。我冒昧地让它更具可读性。还请阅读[问],然后添加您编写的代码以获取当前输出和一些样本数据。 – simbabque

回答

-1

这为我工作

s/(KY SPINE & REHAB|SPINE|REHAB)/[$1]/g 

希望它会为你工作,要么

编辑:

这是为我工作一个完整的代码。可以将它用于您的案例或任何其他自定义替换任何字符串。这可能不是一个很酷的班轮,但它的工作原理。希望它更适合您的需求。

use strict; 
use warnings; 

my ($new, $last, $offset, $length, $replace); 

while(<DATA>) { 
    $new = ''; 
    $last = 0; 
    while ($_ =~ m/KY SPINE & REHAB|SPINE|REHAB/g) { 
     $offset = $-[0]; 
     if ($& eq 'KY SPINE & REHAB') { 
      $replace = '[' . $& . ']'; 
     } 
     if ($& eq 'SPINE') { 
      $replace = '(' . $& . ')'; 
     } 
     if ($& eq 'REHAB') { 
      $replace = '(' . $& . ')'; 
     } 
     $length = $offset - $last; 
     $new .= substr($_, $last, $length) . $replace; 
     $last = $+[0]; 
    } 
    $length = length($_) - $last; 
    $new .= substr($_, $last, $length); 
    print $new; 
} 

__DATA__ 
lorem ipsum KY SPINE & REHAB dolor sit amet SPINE consectetur adipiscing elit REHAB sed do eiusmod tempor incididunt ut labore et dolore magna aliqua sit amet SPINE consectetur adipiscing elit REHAB sed do eiusmod tempor 
KY SPINE & REHAB dolor sit amet SPINE consectetur adipiscing elit REHAB sed do eiusmod tempor incididunt ut amet SPINE consectetur adipiscing elit REHAB sed do eiusmod tempor adipiscing elit REHAB sed do eiusmod tempor 
lorem ipsum KY SPINE & REHAB dolor sit amet SPINE consectetur adipiscing elit REHAB sed do eiusmod tempor incididunt ut labore et dolore magna aliqua sit amet SPINE consectetur adipiscing elit REHAB sed do eiusmod tempor 
SPINE sit amet SPINE consectetur REHAB 
SPINE 
sit amet SPINE consectetur KY SPINE & REHAB REHAB 
+0

嗨亚历克斯 - 感谢您的回答。也许我没有正确地问它。我不能在这里做'OR(|)',因为我需要用不同的方式替换这些单词。所以我需要做多次传球。我已经更新了这个问题。 –

+0

@LeslieFrancis嗨Leslie我修复了代码。它应该现在适合你的情况。 –

1

如果这些是你想突出,那么唯一的三个阶段,这将做它为您

perl -i -pe's/(KY SPINE & REHAB|SPINE|REHAB)/$1 =~ tr/&// ? "[$1]" : "($1)"/eg' myfile 
0

如何:

while(<DATA>) { 
    chomp; 
    s/(KY SPINE & REHAB)/[$1]/; 
    s/(SPINE(?!.*REHAB)|(?<!SPINE &)REHAB)/($1)/; 
    say; 
} 

__DATA__ 
KY SPINE & REHAB - when found replace with square brackets around it 
SPINE - when found replace with round brackets around it 
REHAB - when found replace with round brackets around it 

输出:

[KY SPINE & REHAB] - when found replace with square brackets around it 
(SPINE) - when found replace with round brackets around it 
(REHAB) - when found replace with round brackets around it 
+0

这将失败的记录像'xxx xxx SPINE xxx xxx REHAB xxx'。什么是“chomp”? – Borodin

+0

@Borodin:是的,但它适用于给定的例子。 chomp是为了避免输出双重换行。 – Toto

+0

OP没有显示任何示例数据。当你不想打印额外的换行符时,'print'是'say'的一个有用的替代方法。 – Borodin

相关问题