2016-05-09 5 views
1

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

how to replace strings in file based on values from another file? (example inside)

Replacing strings in file, using patterns from another file

У меня есть какие-то сложные файлы, которые выглядят следующим образом:

((PLT_01736:0.06834090301258281819,(((PLT_01758:0.04822932915066913823,PLT_01716:0.08160284537473952438)98:0.04771898687201567291,((PAU_02074:0.04683560272944583408,PAK_01896:0.02826787310445108212)95:0.03010698277052889504,PLT_02424:0.06991513512243620332)99:0.06172493035971356873)90:0.05291396820697712167,((PAK_02014:0.00000187538096058579,PAU_02206:0.00721521619460035492)100:0.43252725913741080221,((PLT_02568:0.06262043352060168988,(PAU_01961:0.02293694470289835488,PAK_01787:0.01049771144617094552)98:0.05833869619359682152)100:0.65266156617675985530,(PAK_03203:0.06403695571262699171,PAU_03392:0.03453883849938884504)99:0.10276841868475847241)2:0.14443958710162313475)10:0.20176450294539299835)9:0.01245548664398392694)92:0.05176685581730120639,(PAK_02606:0.03709141633854080161,PAU_02775:0.01796540370573110335)57:0.01492069367348663675,PLT_01696:0.01562657531699716829); 

(Это формат Newick филогенетических деревьев в случае, если кому-то интересно)

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

Они должны быть заменены на «группы» (оперон) они принадлежат, и поэтому я думал, что делает индексный файл рода будет путь, так, например, PLT_01696 заменяется group_1 сказать :

Keyfile:

PLT_01696 group_1 
PLT_01736 group_1 
PLT_01758 group_1 
.... 
PAU_02074 group_2 

Так что я думаю, что если бы я мог передать файл sed или некоторый эквивалент, заставить его читать и искать записи в колонке один, и заменить его с тем, что я имею спрятать его в столбце 2, это лучший способ сделать это? В конце этого файла будет около 350 отдельных клавиш, которые будут отсортированы в 12 групп.

И файл будет в конечном итоге выглядит как:

((group_1:0.06834090301258281819,(((group_1:0.04822932915066913823,group_1:0.08160284537473952438)98:0.04771898687201567291,..... 

Я открыт для альтернативных предложений, это только казалось, наиболее очевидным для меня. Это на Ubuntu 14.04, поэтому любое решение является честной игрой на самом деле, но я гораздо более уверен в bash (и немного perl).

+0

Вы пробовали что-нибудь? – 123

+2

Вы можете использовать sed для генерации сценария sed из вашего ключевого файла. – choroba

+1

Чтобы добавить комментарий 123: «Вопросы, требующие помощи в домашней работе, должны содержать резюме работы, которую вы сделали до сих пор, чтобы решить проблему, и описание проблемы, которую вы решаете». http://stackoverflow.com/help/on-topic – Mort

ответ

2

Я буду кусать. Давайте называть сценарий phylo.awk:

NR==FNR { pattern[NR] = $1; replacement[NR] = $2; count++; next } 
{ 
    for (i = 1; i <= count; i++) { 
     sub(pattern[i], replacement[i]) 
    } 
    print $0 
} 

Тогда говорят:

awk -f phylo.awk patterns data 
+0

И снова мое невежество к awk - это мое падение: P всегда кажется, что есть решение, в котором борется битвы. Если это делает работу очень элегантной! –

+0

Хотя это не обязательство, всегда полезно дать повод для голосования. + 1d. :). Как я уже догадался, решение awk здесь опрятно. – sjsam

+0

Это сработало фантастически (и достаточно просто для моего слабого мозга, чтобы понять: P) огромное спасибо! –

3

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

PLT_01736 group_1 

затем для каждой строки в этом файле вы хотите создать sed операцию, которая выглядит как:

s/\([,(]\)PLT_01736:/\1group_1:/g 

где g может не потребоваться (Я не знаю, может ли данный оперон более одного раза появляться в одной строке). Начальный класс символов захватывает ( или ,, а \( и \) помнят, что за ним следует специальный идентификационный ключ и двоеточие; операция замены выводит запоминаемый символ, заменяющий текст и двоеточие.Преимущество отслеживания предыдущего и последующих символов заключается в том, что если по какой-то ошибке вы имеете опероны PLT_00100 и PLT_001001 (где один операнд является префиксом другого), отслеживание окружающих символов обеспечивает правильное совпадение. В противном случае вы должны убедиться, что самые длинные совпадения появляются сначала в скрипте, что является fiddlier (sort -r, вероятно, сортирует это, но ...).

Таким образом, предполагая, что отображения в файле mapping.data, вы можете использовать:

sed 's%\([A-Z]*_[0-9]*\) *\(.*\)%s/\\([,(]\\)\1:/\\1\2:/g%' mapping.data > script.sed 
sed -f script.sed newick.phylogenetic.tree.data > transformed.data 

Это использует % в порождающей s%%% операции вывода s/// (это требует некоторой осторожности). Элемент поиска s%%% ищет нулевые или более строчные буквы, символ подчеркивания и ноль или более цифр, фиксируя это с помощью \( и \); за которым следует одно или несколько пробелов, а затем некоторые другие символы, которые также захватываются. Если ключи идентификатора могут иметь другую структуру, то соответствующим образом изменить соответствующее регулярное выражение. Я предполагаю, что входные данные являются «чистыми», поэтому нет необходимости беспокоиться только по линиям обработки с ровно тремя буквами, а также подчеркиванием и ровно пятью цифрами, и нет никаких завершающих пробелов. Если выделены две части (идентификатор ключа и замена), необходимо создать команду s///, не забывая удвоить обратную косую черту, которая должна появиться на выходе.

Учитывая ваши входные данные и список ключей, выход я получаю:

((group_1:0.06834090301258281819,(((group_1:0.04822932915066913823,PLT_01716:0.08160284537473952438)98:0.04771898687201567291,((group_2:0.04683560272944583408,PAK_01896:0.02826787310445108212)95:0.03010698277052889504,PLT_02424:0.06991513512243620332)99:0.06172493035971356873)90:0.05291396820697712167,((PAK_02014:0.00000187538096058579,PAU_02206:0.00721521619460035492)100:0.43252725913741080221,((PLT_02568:0.06262043352060168988,(PAU_01961:0.02293694470289835488,PAK_01787:0.01049771144617094552)98:0.05833869619359682152)100:0.65266156617675985530,(PAK_03203:0.06403695571262699171,PAU_03392:0.03453883849938884504)99:0.10276841868475847241)2:0.14443958710162313475)10:0.20176450294539299835)9:0.01245548664398392694)92:0.05176685581730120639,(PAK_02606:0.03709141633854080161,PAU_02775:0.01796540370573110335)57:0.01492069367348663675,group_1:0.01562657531699716829); 
0
#!/bin/bash 

while read i;do #enter your loop 

a=$(echo "$i" | cut -d" " -f1) #get what to find 
b=$(echo "$i" | cut -d" " -f2) #get what to replace with 

sed -i "s/$a/$b/g" input.txt #find and replace -i is "in place" 

done <ref.txt #define file you're looping through 

вход:

((PLT_01736:0.06834090301258281819,(((PLT_01758:0.04822932915066913823,PLT_01716:0.08160284537473952438)98:0.04771898687201567291,((PAU_02074:0.04683560272944583408,PAK_01896:0.02826787310445108212)95:0.03010698277052889504,PLT_02424:0.06991513512243620332)99:0.06172493035971356873)90:0.05291396820697712167,((PAK_02014:0.00000187538096058579,PAU_02206:0.00721521619460035492)100:0.43252725913741080221,((PLT_02568:0.06262043352060168988,(PAU_01961:0.02293694470289835488,PAK_01787:0.01049771144617094552)98:0.05833869619359682152)100:0.65266156617675985530,(PAK_03203:0.06403695571262699171,PAU_03392:0.03453883849938884504)99:0.10276841868475847241)2:0.14443958710162313475)10:0.20176450294539299835)9:0.01245548664398392694)92:0.05176685581730120639,(PAK_02606:0.03709141633854080161,PAU_02775:0.01796540370573110335)57:0.01492069367348663675,PLT_01696:0.01562657531699716829); 

исх:

PLT_01696 group_1 
PLT_01736 group_1 
PLT_01758 group_1 
PAU_02074 group_2 

выход:

((group_1:0.06834090301258281819,(((group_1:0.04822932915066913823,PLT_01716:0.08160284537473952438)98:0.04771898687201567291,((group_2:0.04683560272944583408,PAK_01896:0.02826787310445108212)95:0.03010698277052889504,PLT_02424:0.06991513512243620332)99:0.06172493035971356873)90:0.05291396820697712167,((PAK_02014:0.00000187538096058579,PAU_02206:0.00721521619460035492)100:0.43252725913741080221,((PLT_02568:0.06262043352060168988,(PAU_01961:0.02293694470289835488,PAK_01787:0.01049771144617094552)98:0.05833869619359682152)100:0.65266156617675985530,(PAK_03203:0.06403695571262699171,PAU_03392:0.03453883849938884504)99:0.10276841868475847241)2:0.14443958710162313475)10:0.20176450294539299835)9:0.01245548664398392694)92:0.05176685581730120639,(PAK_02606:0.03709141633854080161,PAU_02775:0.01796540370573110335)57:0.01492069367348663675,group_1:0.01562657531699716829); 
+0

Выполняет команду 'cut' дважды, а команда' sed' - для каждого сопоставления. Это неэффективно по сравнению с чтением файла сопоставления один раз и файла данных один раз, - что другие ответы достигают. –