чувствительная к регистру замена; те же целевые идентификаторы

#!/bin/sh

for f in comp1/* ; do
  diff "comp1/$f" "comp2/$f" > "$f.diff"
done

Этот сценарий предполагает, что у Вас есть файлы того же имени в обоих каталогах.

4
06.03.2014, 11:36
2 ответа

С sed ничего подобного нельзя сделать, это просто редактор текстового потока. Попробуйте этот сценарий Perl:

#!/usr/bin/env perl 

## Set the record separator to \n\n to
## read multiple lines as a single record
$/="\n\n";
## This array will contain all lines of the file
my @lines=<>;

## The list of suffixes
@suffix=(a..z); 

## For each line of the input file
foreach (@lines) {
    ## If the current line (lines are now the actual multiline records
    ## because we set $/ to consecutive newlines) is one we are interested in.
    if (/isoforms.*?Target=(\S+)/s){
    ## Keep a list of seen targets
    $seen{$1}++;
    }

}
## Now that we have processed the entire file
## go back and print each line.
foreach (@lines) {

    ## If this line is one of the ones we're interested in
    if(/Name=(.+?);.*?isoforms=.*?Target=(\S+)/s){
    $name=$1; $target=$2;
    ## This is needed so we can know whether
    ## how many times we've seen this target so far.
    $newseen{$target}++;
    ## If this target exists more than once in the input file
    if ($seen{$target}>1) {
        ## Use the %newseen hash to choose the right letter.
        ## The -1 is needed because the first element of an
        ## array is 0, not 1.
        s/$name/$target.$suffix[$newseen{$target}-1]/;
    }
    else {
        s/$name/$target/;
    }
    }
    print;
}

Сохраните приведенный выше сценарий как foo.pl , сделайте его исполняемым ( chmod a + x foo.pl ) и запустите во входном файле:

./foo.pl input.txt > output.txt
4
27.01.2020, 20:56

Забудьте, что я писал раньше, я думал, что вы перемещаете файлы. Думаю, теперь я понимаю его лучше:

sed -r '/isoforms/{\
    N;N;s/(.*Name=)[^;]*(.*Name=)\S*\
    (.*Name=.*Target=)(\S*)(.*)/\
        \1\4\2\4\3\4\5/}'

Я запустил его, и он работает для замены первых двух вхождений "Name=code[0-9_]*" в любом наборе из трех строк, начиная с одной, содержащей "isoforms", на следующую встречающуюся не пробельную последовательность $VALUE из пары ключей "Target=$VALUE".

Я использовал только образец из 20 или около того строк; так что, возможно, он нуждается в настройке. Кроме того, я не уверен, что понимаю проблему суффикса ".[a|b]", о которой вы упоминаете, хотя я уверен, что еще не решил ее. Я вполне уверен, что с чем бы это ни было, с этим можно справиться с помощью теста ветвления или двух. Я попытаюсь объяснить, что означает код:

  • /isoforms/ sed сначала просматривает поток на наличие строки, содержащей эту строку.

  • { Когда она найдена, он начинает выполнять блок кода, расположенный в фигурных скобках. }

  • N;N; sed немедленно считывает следующие две строки ввода в свое пространство шаблонов, так что он может работать с тремя строками одновременно. Если бы в этот момент вы использовали команду "l" для печати пространства шаблонов, вы бы увидели что-то вроде:

    изоформы строка \n ген строка \n цель строка

  • s/search/replace/ команда s инструктирует sed выполнить функцию поиска и замены в текущем пространстве шаблонов.

  • (regex) каждая паренс-пара в поле поиска регулярного выражения соответствует обратной ссылке в поле замены. Некоторые сокращения, которые я использовал:

    • [^;]* следующая встречающаяся самая длинная последовательность символов, не включающая точку с запятой.

    • \S* следующая по длине последовательность символов, не включающая пробелы.

  • \NUM sed увеличивает заменяющие обратные ссылки в порядке их определения в поле поиска. Краткое описание этого конкретного поиска:

    • \1 sed ищет строку "Name=" и, найдя три в пространстве шаблона и три, указанные в regex, сопоставляет все до первого результата включительно.

    • DISCARDED sed отбрасывает самую длинную последовательность символов, которую он может найти после \1, не включая точку с запятой.

    • \2 Аналогично \1, но для второго результата "Name=".

    • DISCARDED sed отбрасывает следующую встречающуюся последовательность символов, пока не встретит пробел.

    • \3 sed подбирает "Name=" и все остальное до "Target=" включительно

    • \4 sed подбирает следующую последовательность символов, пока не встретится пробел

    • \5 sed подбирает то, что осталось от строки 3

  • Чтобы собрать все вместе, я просто заменил секции DISCARDED на \4 следующим образом:

    \1\4\2\4\3\4\5

INPUT:

ID=gene09491;Name=code_229633_138;isoforms=1
ID=mRNA10690;Parent=gene09491;Name=code_229633_138
ID=exon26252;Parent=mRNA10690;Name=code_229633_138;Target=R77_09738T0 1 411 +

ID=gene09513;Name=code_230519_10;isoforms=1
ID=mRNA10715;Parent=gene09513;Name=code_230519_10
ID=exon26311;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 1 59 + ID=exon26312;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 60 186 +

OUTPUT:

ID=gene09491;Name=R77_09738T0;isoforms=1
ID=mRNA10690;Parent=gene09491;Name=R77_09738T0
ID=exon26252;Parent=mRNA10690;Name=code_229633_138;Target=R77_09738T0 1 411 +

ID=gene09513;Name=R77_04813T0;isoforms=1
ID=mRNA10715;Parent=gene09513;Name=R77_04813T0
ID=exon26311;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 1 59 +
ID=exon26312;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 60 186 +

0
27.01.2020, 20:56

Теги

Похожие вопросы