2

GNU sed 可以用来根据行识别模式吗?或者换句话说,如何在您使用 sed 到 ID 的模式中插入换行符?

例如,在以下数据集中(实际上要大得多),我有一个错误,当我搜索重复项时应该删除,但不是因为两行中的信息略有不同(此时无关紧要) )。

在这种情况下,我想从原始文件中完全删除错误。换句话说,如果在我的文件中,两行rs####相互跟随,我想删除这两个副本,以及它们后面的六行. 将它们重新定位到新文件会很好,但最关键的是它们已从原始文件中删除。

rs1038864   16  73762557    A   G
1   1633    0.5835  -0.0004 0.0035
1   1643    0.8902  0.004436    0.004354
0   0   0   0   0
rs1019567   16  83343715    G   T
rs1019567   16  83343715    G   T
1   1641    0.4692  0.0009  0.0035
1   559 0.4612  -0.0025 0.0060
1   1643    0.5178  -0.002244   0.002745
1   1643    0.5178  -0.002244   0.002745
1   1909    0.493842692 0.0008  0.0027
1   1950    0.493842692 0.0008  0.0027
rs1038556   16  55132072    C   T
1   6388    0.7773  0.0020  0.0044
1   6843    0.1161  0.001379    0.004275
1   1509    0.978660942 0.0041  0.0096
rs1019797   16  87788686    C   G
rs1019797   16  87788686    C   G
1   1639    0.717   0.0022  0.0038
1   5557    0.7193  0.0020  0.0064
1   1643    0.6691  -0.001044   0.002888
1   6843    0.6691  -0.001044   0.002888
1   1959    0.315280799 -0.0041 0.0032
1   1909    0.315280799 -0.0041 0.0032
rs1038887   16  62660698    A   G
1   1688    0.4947  -0.0028 0.0035
0   0   0   0   0
1   1909    0.464393658 0.0007  0.0028

就像是,

sed -i '/^rs.*d
^rs.*/,+6d' test.data

也许

sed -i '/^rs.*;^rs.*/,+6d' test.data

? 任何想法将不胜感激!

4

2 回答 2

2

我不认为sed是适合这项工作的工具(但我可能错了;这部分取决于是否总是正好有 6 行要删除,并且可能取决于相邻的 ID 行是否总是具有相同的 ID)。您可能可以使用 来做到这一点awk,但我会使用 Perl:

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

my $rejects = "reject.lines";
open my $fh, '>', $rejects or die "Failed to create $rejects";

my $old = "";

while (<>)
{
    if ($_ =~ /^rs\d+ /)
    {
        if ($old =~ /^rs\d+ /)
        {
            print $fh $old;
            print $fh $_;
            while (<>)
            {
                last if /^rs\d+ /;
                print $fh $_;
            }
            $old = $_;
            next;
        }
    }
    print $old;
    $old = $_;
}
print $old if $old ne "";
close $fh;

这将处理相邻标记线之后的任意数量的线,并且不依赖于两个标记是否相同。

输出

rs1038864   16  73762557    A   G
1   1633    0.5835  -0.0004 0.0035
1   1643    0.8902  0.004436    0.004354
0   0   0   0   0
rs1038556   16  55132072    C   T
1   6388    0.7773  0.0020  0.0044
1   6843    0.1161  0.001379    0.004275
1   1509    0.978660942 0.0041  0.0096
rs1038887   16  62660698    A   G
1   1688    0.4947  -0.0028 0.0035
0   0   0   0   0
1   1909    0.464393658 0.0007  0.0028

拒绝行

rs1019567   16  83343715    G   T
rs1019567   16  83343715    G   T
1   1641    0.4692  0.0009  0.0035
1   559 0.4612  -0.0025 0.0060
1   1643    0.5178  -0.002244   0.002745
1   1643    0.5178  -0.002244   0.002745
1   1909    0.493842692 0.0008  0.0027
1   1950    0.493842692 0.0008  0.0027
rs1019797   16  87788686    C   G
rs1019797   16  87788686    C   G
1   1639    0.717   0.0022  0.0038
1   5557    0.7193  0.0020  0.0064
1   1643    0.6691  -0.001044   0.002888
1   6843    0.6691  -0.001044   0.002888
1   1959    0.315280799 -0.0041 0.0032
1   1909    0.315280799 -0.0041 0.0032
于 2013-01-31T01:41:43.810 回答
2

如果infile包含列出的输入,应该这样做(GNU sed):

<infile sed -r 'N; /([^\n]+)\n\1/ { N; N; N; N; N; N; d }; P; D'

如果要保存已删除的位以deleted.txt使用它:

<infile sed -r 'N; /([^\n]+)\n\1/ { N; N; N; N; N; N; w deleted.txt
d }; P; D'

请注意,该w命令需要以换行符终止。

解释

这会将第二行加载到模式空间 ( N) 并检查这些行是否重复 ( /([^\n]+)\n\1/),是否还有六行被加载到模式空间并被删除 ( d)。

于 2013-01-31T01:42:03.497 回答