有 perl 或 awk 解决这个问题吗?

有 perl 或 awk 解决这个问题吗?

我有一个输入文件(输入.txt)如下所示。

id1      id2       name    weight 
53723848 12651711 timburnes 1.36667
53530214 12651711 timburnes 1.51191
53723848 53530214 timburnes 1.94
764157 52986038 ericcartman 0.861145
56797854 764157 ericcartman 1.35258
56797854 52986038 ericcartman 1.73781

注意第一行不是实际文件的一部分,为了清楚起见,我将其添加到此处

id1我正在尝试将和的值提取id2到两个名为唯一.txt重复.txt

如果我的weight列值大于 1.5,则意味着我有重复的 ID。在这种情况下,我会将id1值移至unique.txt文件并将id2值移至duplicate.txt文件。

如果我的体重列小于 1.5,则意味着我没有重复值。因此,在这种情况下,我将把 和id1id2移至 唯一.txt文件。

因此,对于上述输入,我期望输出为,

为了唯一.txt文件,

53723848 timburnes
764157 ericcartman
56797854 ericcartman

为了重复.txt文件,

12651711 timburnes
53530214 timburnes
52986038 ericcartman

我可以使用下面的代码找出重复项。

要根据第 4 列获取大于 1.5 的值,

awk -F" " '$4 >= 1.5 { print $1" " $2" " $3" " $4}' file1.txt > Output.txt

现在,对于大于 1.5 的值,我可以使用下面的代码根据名称合并重复的 id。

  perl -ane 'foreach(@F[0..1]){$k{$F[2]}{$_}++}
           END{
                foreach $v (sort keys(%k)){
                    print "$_ " foreach(keys(%{$k{$v}})); 
                    print "$v\n"
                }; 
            } ' Output.txt

但是,我无法在上述方法中以我喜欢的方式获得输出。

编辑:

我正在为我的输入运行命令,如下所示。

awk '{
      if ($4 > 1.5) { 
          if (++dup[$2] == 1)  print $2, $3 > "duplicate.txt"
      } 
      else
          if (++uniq[$1] == 1) print $1, $3 > "unique.txt" 
}' << END
17412193 43979400 ericcartman 2.16667
21757330 54678379 andrewruss 0.55264
END 

我得到的输出为,

-bash-3.2$ cat unique.txt
21757330 a.andreev
-bash-3.2$ cat duplicate.txt
43979400 ericcartman

然而,我期望的输出是,

cat unique.txt
17412193 ericcartman
21757330 andrewruss
54678379 andrewruss
cat duplicate.txt
43979400 ericcartman

答案1

这是awk解决方案:

$ awk '
    $4 < 1.5 {
      uniq[$1] = $3;
      uniq[$2] = $3;
      next;
  }
  {
      uniq[$1] = $3;
      dup[$2] = $3;
      delete uniq[$2];
  }
  END {
    print "--unique.txt--";
    for(i in uniq) {
        print i,uniq[i]
    }
    print "";
    print "--duplicate.txt--";
    for(i in dup) {
        print i,dup[i]
    }
    }' file
--unique.txt--
764157 ericcartman
56797854 ericcartman
53723848 timburnes

--duplicate.txt--
53530214 timburnes
52986038 ericcartman
12651711 timburnes

用你的第二个例子:

$ awk '
    $4 < 1.5 {
      uniq[$1] = $3;
      uniq[$2] = $3;
      next;
  }
  {
      uniq[$1] = $3;
      dup[$2] = $3;
      delete uniq[$2];
  }
  END {
    print "--unique.txt--";
    for(i in uniq) {
        print i,uniq[i]
    }
    print "";
    print "--duplicate.txt--";
    for(i in dup) {
        print i,dup[i]
    }
    }' << END
> 17412193 43979400 ericcartman 2.16667
> 21757330 54678379 andrewruss 0.55264
END
--unique.txt--
21757330 andrewruss
54678379 andrewruss
17412193 ericcartman

--duplicate.txt--
43979400 ericcartman

答案2

$ awk '{
      if ($4 > 1.5) { 
          if (++dup[$2] == 1)  print $2, $3 > "duplicate.txt"
      } 
      else
          if (++uniq[$1] == 1) print $1, $3 > "unique.txt" 
}' << END
53723848 12651711 timburnes 1.36667
53530214 12651711 timburnes 1.51191
53723848 53530214 timburnes 1.94
764157 52986038 ericcartman 0.861145
56797854 764157 ericcartman 1.35258
56797854 52986038 ericcartman 1.73781
END

$ cat unique.txt 
53723848 timburnes
764157 ericcartman
56797854 ericcartman

$ cat duplicate.txt 
12651711 timburnes
53530214 timburnes
52986038 ericcartman

答案3

这是一个 Perl 的:

perl -lane '$F[3]>1.5 ? print STDERR "$F[1] $F[2]" : print STDOUT "$F[0] $F[2]"'\
 input.txt 2> duplicate.txt > unique.txt

我不会在这里检查重复项,如果我正确理解您的问题,那么您已经这样做了,并且某些内容是否是重复的取决于最后一个字段的值。如果我误解了某些内容,请告诉我,我会更新。

上面的代码产生

$ cat duplicate.txt 
12651711 timburnes
53530214 timburnes
52986038 ericcartman

$ cat unique.txt 
53723848 timburnes
764157 ericcartman
56797854 ericcartman

相关内容