使用Perl识别伪重复项

时间:2013-10-11 13:38:17

标签: regex perl duplicates

我有一个包含名字的列表。有多个同名。我想抓住这些伪欺骗的第一个实例并锚定它们。

示例输入

Josh Smith
Josh Smith0928340938
Josh Smith and friends

hello
hello1223
hello and goodbye.

我想要做的是确定第一次出现Josh Smithhello并在其前面放置一个诸如管道|之类的锚点进行验证。这些也是通配符,因为列表很大,所以我不能专门寻找Josh Smith的第一个匹配,依此类推。

我想要的输出是这样的:

|Josh Smith
Josh Smith0928340938
Josh Smith and friends

|hello
hello1223
hello and goodbye.

我没有提供任何代码。关于如何解决这个问题,我有点不知所措,希望也许有人使用正则表达式或Perl处于相似的情况。

2 个答案:

答案 0 :(得分:1)

我认为根据我对你的要求的理解,你正在寻找这样的东西:

$prefix = '';
$buffered = '';
$count = 0;
while ($line = <>) {
    $linePrefix = substr($line,0,length($prefix));
    if ($buffered ne '' && $linePrefix eq $prefix) {
        $buffered .= $line; 
        $count++;
    } else {
        if  ($buffered ne '') {
            print "|" if ($count > 1);  
            print $buffered;
        }
        $buffered = $line;
        $prefix = $line;
        chomp $prefix;
        $count = 1;
    }
}
if ($buffered ne '') {
    if ($count > 1) {
        print "|";
    }
    print $buffered;
}

答案 1 :(得分:1)

实际上,IMO这是一个相当有趣的问题,因为你可以有创意。由于你不知道如何识别根名称,我不得不问你是否需要?我觉得你不需要一个完美的解决方案。因此,我会选择一些简单的事情:

#!/usr/bin/perl -wn
$N = 4;

if (@prev) {
    $same_start = length $_ >= $N &&
        substr($prev[0], 0, $N) eq substr($_, 0, $N);

    unless ($same_start) {
        print "|", shift @prev if $#prev;
        @prev = grep { print;0 } @prev;
    }
}
push @prev, $_;

}{ print for @prev

编辑:修复bug:&lt; print“|”,shift @prev;&gt; to&lt; print“|”,如果$#prev,则转移@prev;&gt;

示例输出:

$ perl josh.pl <josh-input.txt
|Josh Smith
Josh Smith0928340938
Josh Smith and friends

|hello
hello1223
hello and goodbye.