#!/bin/sh
for f in comp1/* ; do
diff "comp1/$f" "comp2/$f" > "$f.diff"
done
Этот сценарий предполагает, что у Вас есть файлы того же имени в обоих каталогах.
С 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
Забудьте, что я писал раньше, я думал, что вы перемещаете файлы. Думаю, теперь я понимаю его лучше:
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 +