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

Я изо всех сил стараюсь сделать случайную замену в текстовом файле. Ниже приведен фрагмент моего файла sed, который я запускаю как sed -f file.sed <input.txt> output.txt

s/\<code_229633_13\>/R77_08349T0/ s/\<code_229633_138\>/R77_09738T0/ s/\<code_230519_10\>/R77_04813T0/ s/\<code_230519_1\>/R77_13591T0/ s/\<code_230519_13\>/R77_05463T0/ up to line 14521.... 

Код работает отлично, но у меня также есть случаи, когда у меня есть 2 или более идентификатора TARGET (code_010512_23 и code_299097_0), ovelapping тот же идентификатор REPLACEMENT (R77_14520T0), и я хотел бы иметь в качестве вывода что-то вроде R77_14520T0.a и R77_14520T0.b (строки 1 и 2 ниже)

 s/code_010512_23/R77_14520T0/ --> R77_14520T0.a s/code_299097_0/R77_14520T0/ --> R77_14520T0.b 

Более того, более сложный, но схожий случай, когда у меня есть следующий входной файл (файл input2.txt) :

  ID=gene09464;Name=code_229633_13;isoforms=1 ID=mRNA10661;Parent=gene09464;Name=code_229633_13 ID=exon26192;Parent=mRNA10661;Name=code_229633_13;Target=R77_08349T0 1 1093 + ID=exon26193;Parent=mRNA10661;Name=code_229633_13;Target=R77_08349T0 1094 1873 + 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 + ID=gene09511;Name=code_230519_1;isoforms=1 ID=mRNA10713;Parent=gene09511;Name=code_230519_1 ID=exon26308;Parent=mRNA10713;Name=code_230519_1;Target=R77_13591T0 1 1075 + ID=exon26309;Parent=mRNA10713;Name=code_230519_1;Target=R77_13591T0 1076 1128 + ID=gene09514;Name=code_230519_13;isoforms=1 ID=mRNA10716;Parent=gene09514;Name=code_230519_13 ID=exon26316;Parent=mRNA10716;Name=code_230519_13;Target=R77_05463T0 1 219 + ID=gene00865;Name=code_010512_23;isoforms=1 ID=mRNA00979;Parent=gene00865;Name=code_010512_23 ID=exon02477;Parent=mRNA00979;Name=code_010512_23;Target=R77_14520T0 1 143 + ID=gene14561;Name=code_299097_0;isoforms=2 ID=mRNA16419;Parent=gene14561;Name=code_299097_0 ID=exon39828;Parent=mRNA16419;Name=code_299097_0;Target=R77_14520T0 144 193 + ID=mRNA16420;Parent=gene14561;Name=code_299097_0 ID=exon39828;Parent=mRNA16420;Name=code_299097_0;Target=R77_15554T0 408 457 + 

и мне нужно применить замены так же, как и предыдущие, только на строках, которые содержат слово «изоформы», другими словами, в строках 1,6,10, 15,20, 24 и 28 и нигде в тексте , Формат этого входного файла будет точно таким же, как изображены пустыми строками среди строк «изоформы».

Мой желаемый результат

  ID=gene09464;Name=R77_08349T0;isoforms=1 ID=mRNA10661;Parent=gene09464;Name=code_229633_13 ID=exon26192;Parent=mRNA10661;Name=code_229633_13;Target=R77_08349T0 1 1093 + ID=exon26193;Parent=mRNA10661;Name=code_229633_13;Target=R77_08349T0 1094 1873 + ID=exon26194;Parent=mRNA10661;Name=code_229633_13;Target=R77_08349T0 1874 4065 + ID=gene09491;Name=R77_09738T0;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=Target=R77_04813T0;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 + ID=exon26313;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 187 678 + ID=exon26314;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 679 1399 + ID=exon26315;Parent=mRNA10715;Name=code_230519_10;Target=R77_04813T0 1400 1402 + ID=gene09511;Name=R77_13591T0;isoforms=1 ID=mRNA10713;Parent=gene09511;Name=code_230519_1 ID=exon26308;Parent=mRNA10713;Name=code_230519_1;Target=R77_13591T0 1 1075 + ID=exon26309;Parent=mRNA10713;Name=code_230519_1;Target=R77_13591T0 1076 1128 + ID=gene09514;Name=R77_05463T0;isoforms=1 ID=mRNA10716;Parent=gene09514;Name=code_230519_13 ID=exon26316;Parent=mRNA10716;Name=code_230519_13;Target=R77_05463T0 1 219 + ID=gene00865;Name=R77_14520T0.a;isoforms=1 ID=mRNA00979;Parent=gene00865;Name=code_010512_23 ID=exon02477;Parent=mRNA00979;Name=code_010512_23;Target=R77_14520T0 1 143 + ID=gene14561;Name=R77_14520T0.b;isoforms=2 ID=mRNA16419;Parent=gene14561;Name=code_299097_0 ID=exon39828;Parent=mRNA16419;Name=code_299097_0;Target=R77_14520T0 144 193 + ID=mRNA16420;Parent=gene14561;Name=code_299097_0 ID=exon39828;Parent=mRNA16420;Name=code_299097_0;Target=R77_15554T0 408 457 + 

Вы не можете действительно делать подобные вещи с помощью 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 _] * » на любой набор из трех строк, начинающихся с одного, содержащего « изоформы », со следующей встречной не-пробельной последовательностью $ VALUE пара ключей « Target = $ VALUE ».

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

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

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

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

    линия изоформы line \ n генная линия \ n целевая линия

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

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

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

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

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

    • \ 1 sed ищет строку « Name = » и, найдя три в пространстве шаблонов и три указанные в регулярном выражении, соответствует всем параметрам вплоть до первого результата.

    • 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

ВХОД:

ID = gene09491; Name = code_229633_138; изоформы = 1
ID = mRNA10690; Родитель = gene09491; Name = code_229633_138
ID = exon26252; Parent = mRNA10690; Name = code_229633_138; Target = R77_09738T0 1 411 +

ID = gene09513; Name = code_230519_10; изоформы = 1
ID = mRNA10715; Родитель = 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 +

ВЫВОД:

ID = gene09491; Name = R77_09738T0; изоформы = 1
ID = mRNA10690; Родитель = gene09491; Name = R77_09738T0
ID = exon26252; Parent = mRNA10690; Name = code_229633_138; Target = R77_09738T0 1 411 +

ID = gene09513; Name = R77_04813T0; изоформы = 1
ID = mRNA10715; Родитель = 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 +