Использование sed для идентификации шаблона в строках, а не в Столбцах


Можно ли использовать GNU sed для идентификации шаблона на основе строк? Или другими словами, как вы можете вставить разрыв строки в шаблон, который вы используете sed для идентификации?

Например, в следующем наборе данных (который на самом деле намного больше) у меня есть ошибка, которая должна была быть удалена, когда я искал дубликаты, но не была, потому что информация немного отличается в двух строках (что не имеет значения на данный момент).

В этом случае я хочу полностью удалить ошибку из оригинал file.In другими словами, если в моем файле две строки 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

? Любые мысли будут оценены!

2 2

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).

Я не думаю, что 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