使用perl从文本文件中删除唯一行

使用perl从文本文件中删除唯一行,perl,Perl,我在perl中对包含多列的文本文件进行过滤 该文件具有以下格式: C1 C2 C3 C4 1 .. .. .. 2 .. .. .. 3 .. .. .. 3 .. .. .. 3 .. .. .. 我想删除第1列中具有唯一值的所有行。所以输出应该是这样的: C1 C2 C3 C4 3 .. .. .. 3 .. .. .. 3 .. .. .. 我正在对此文件执行不同的筛选步骤。这是我正在使用的脚本 my $ D

我在perl中对包含多列的文本文件进行过滤

该文件具有以下格式:

C1  C2  C3  C4 
1   ..  ..  ..
2   ..  ..  ..
3   ..  ..  ..
3   ..  ..  ..
3   ..  ..  ..
我想删除第1列中具有唯一值的所有行。所以输出应该是这样的:

C1  C2  C3  C4
3   ..  ..  ..
3   ..  ..  ..
3   ..  ..  ..
我正在对此文件执行不同的筛选步骤。这是我正在使用的脚本

my $ DATA
my $filename = $ARGV[0];
    unless ($filename) {
        print "Enter filename:\n";
        $filename = <STDIN>;
        chomp $filename;
     }
open($DATA,'<',$filename) or die "Could not open file $filename $!";
open($OUT,'+>',"processed.txt") or die "Can't write new file: $!";

while(<$DATA>){
    next if /^\s*#/; 
    print $OUT $_;
    }

close $OUT;
my$DATA
我的$filename=$ARGV[0];
除非($filename){
打印“输入文件名:\n”;
$filename=;
chomp$filename;
}
打开($DATA,,“processed.txt”)或死亡“无法写入新文件:$!”;
while(){
下一个if/^\s*#/;
打印$OUT$;
}
收尾美元;
正如您所看到的,我正在一个while循环中工作,在这个循环中,我已经使用了next命令从文件中删除注释行。现在,我想向这个循环添加一个命令,以删除列1中具有唯一值的所有行


有人能帮我一下吗?

首先,让我们把程序中的无关内容处理掉

while (<>) {
   next if /^\s*#/; 
   print;
}
在继续阅读之前,我们不知道是否会有重复的内容,所以我们需要存储行以便以后使用

push @{ $by_id{$id} }, $_;
一旦我们看完了文件,我们就可以打印出多行ID的行

for my $id (keys(%by_id)) {
    print @{ $by_id{$id} } if @{ $by_id{$id} } > 1;
}
最后,您未能处理标头,这可以使用

print scalar(<>);

首先,让我们从您的程序中删除无关的内容

while (<>) {
   next if /^\s*#/; 
   print;
}
在继续阅读之前,我们不知道是否会有重复的内容,所以我们需要存储行以便以后使用

push @{ $by_id{$id} }, $_;
一旦我们看完了文件,我们就可以打印出多行ID的行

for my $id (keys(%by_id)) {
    print @{ $by_id{$id} } if @{ $by_id{$id} } > 1;
}
最后,您未能处理标头,这可以使用

print scalar(<>);
my%id\u计数;
while(我的$line=){
如果$line=~/^\s*#/,则下一步;
my($id)=拆分(/\s+/,$line,1);
$id_count{$id}{lines}.=$line;
$id_count{$id}{counter}++;
}
打印$OUT join(“,映射{$id\u count{$\u}{lines}}grep{$id\u count{$\u}{counter}ne“1”}键%id\u count);
编辑: 如果要保持行的排序,只需在最后一行的
grep
之前添加
sort

my%id\u count;
while(我的$line=){
如果$line=~/^\s*#/,则下一步;
my($id)=拆分(/\s+/,$line,1);
$id_count{$id}{lines}.=$line;
$id_count{$id}{counter}++;
}
打印$OUT join(“,映射{$id\u count{$\u}{lines}}grep{$id\u count{$\u}{counter}ne“1”}键%id\u count);
编辑:
如果要保持行的排序,只需在最后一行的
grep
之前添加一个
sort

大部分是从ikegami和mattan偷来的:

print "header: ", scalar(<>);
print "multis: \n";

my %seen;
while (<>) {
   next if /^\s*#/;
   my ($id) = /^(\S+)/;
   ++$seen{$id}{count};
   if (1 == $seen{$id}{count}) {
      # store first occurrence
      $seen{$id}{line} = $_;
   } elsif (2 == $seen{$id}{count}) {
      # print first & second occurrence
      print $seen{$id}{line};
      print $_;
   } else {
      # print Third ... occurrence
      print $_;
   }
}
打印“标题:”,标量();
打印“multis:\n”;
我看到的百分比;
而(){
下一个if/^\s*#/;
我的($id)=/^(\S+/;
++$SEED{$id}{count};
if(1==$seen{$id}{count}){
#存储第一个事件
$seen{$id}{line}=$\;
}elsif(2==$SEED{$id}{count}){
#打印第一次和第二次出现
打印$seen{$id}{line};
打印美元;
}否则{
#打印第三个…事件
打印美元;
}
}
但保持秩序,只使用一个循环

稍后:

三思而后行

是的,它们(线条)应该保持与现在一样,即数字形式 [身份证的]命令

我可以退还索伦的货物:

print "header: ", scalar(<>);
print "multis: \n";

my $ol = scalar(<>);                      # first/old line
my $oi = 0 + (split(" ", $ol, 2))[0];     # first/old id
my $bf = -1;                              # assume old line must be printed
do {
   my $cl = scalar(<>);                   # current line
   my $ci = 0 + (split(" ", $cl, 2))[0];  # current id
   if ($oi != $ci) {                      # old and current id differ
      $oi = $ci;                          #   remember current/first line of current id
      $ol = $cl;                          #   current id becomes old
      $bf = -1;                           #   assume first/old line must be printed
   } else {                               # old and current id are equal
      if ($bf) {                          #    first/old line of current id must be printed
        print $ol;                        #      do it
        $bf = 0;                          #      but not again
      }
      print $cl;                          #    print current line for same id
   }
} while (! eof());
打印“标题:”,标量();
打印“multis:\n”;
我的$ol=scalar();#一线/老线
我的$oi=0+(拆分(“,$ol,2))[0];#第一个/旧id
我的$bf=-1;#假设必须打印旧行
做{
我的$cl=scalar()#当前行
我的$ci=0+(拆分(“,$cl,2))[0];#当前id
如果($oi!=$ci){旧id和当前id不同
$oi=$ci;#记住当前id的当前/第一行
$ol=$cl;#当前id变旧
$bf=-1;#假设必须打印第一行/旧行
}否则{#旧id和当前id相等
如果($bf){必须打印当前id的第一行/旧行
打印$ol;#完成它
$bf=0;#但不会再次出现
}
打印$cl;#打印相同id的当前行
}
}而(!eof());

大部分是从ikegami和mattan偷来的:

print "header: ", scalar(<>);
print "multis: \n";

my %seen;
while (<>) {
   next if /^\s*#/;
   my ($id) = /^(\S+)/;
   ++$seen{$id}{count};
   if (1 == $seen{$id}{count}) {
      # store first occurrence
      $seen{$id}{line} = $_;
   } elsif (2 == $seen{$id}{count}) {
      # print first & second occurrence
      print $seen{$id}{line};
      print $_;
   } else {
      # print Third ... occurrence
      print $_;
   }
}
打印“标题:”,标量();
打印“multis:\n”;
我看到的百分比;
而(){
下一个if/^\s*#/;
我的($id)=/^(\S+/;
++$SEED{$id}{count};
if(1==$seen{$id}{count}){
#存储第一个事件
$seen{$id}{line}=$\;
}elsif(2==$SEED{$id}{count}){
#打印第一次和第二次出现
打印$seen{$id}{line};
打印美元;
}否则{
#打印第三个…事件
打印美元;
}
}
但保持秩序,只使用一个循环

稍后:

三思而后行

是的,它们(线条)应该保持与现在一样,即数字形式 [身份证的]命令

我可以退还索伦的货物:

print "header: ", scalar(<>);
print "multis: \n";

my $ol = scalar(<>);                      # first/old line
my $oi = 0 + (split(" ", $ol, 2))[0];     # first/old id
my $bf = -1;                              # assume old line must be printed
do {
   my $cl = scalar(<>);                   # current line
   my $ci = 0 + (split(" ", $cl, 2))[0];  # current id
   if ($oi != $ci) {                      # old and current id differ
      $oi = $ci;                          #   remember current/first line of current id
      $ol = $cl;                          #   current id becomes old
      $bf = -1;                           #   assume first/old line must be printed
   } else {                               # old and current id are equal
      if ($bf) {                          #    first/old line of current id must be printed
        print $ol;                        #      do it
        $bf = 0;                          #      but not again
      }
      print $cl;                          #    print current line for same id
   }
} while (! eof());
打印“标题:”,标量();
打印“multis:\n”;
我的$ol=scalar();#一线/老线
我的$oi=0+(拆分(“,$ol,2))[0];#第一个/旧id
我的$bf=-1;#假设必须打印旧行
做{
我的$cl=scalar()#当前行
我的$ci=0+(拆分(“,$cl,2))[0];#当前id
如果($oi!=$ci){旧id和当前id不同
$oi=$ci;#记住当前id的当前/第一行
$ol=$cl;#当前id变旧
$bf=-1;#假设必须打印第一行/旧行
}否则{#旧id和当前id相等
如果($bf){必须打印当前id的第一行/旧行
打印$ol;#完成它
$bf=0;#但不会再次出现