AWK: извлечение столбцов из файла: строки имеют переменные столбцы.

У меня есть текстовый файл в следующем формате. Каждая строка имеет переменное количество столбцов.

Файл:

gi|269201691|ref|YP_003280960.1| chromosomal replication initiation protein                                                            gi|57651109|ref|YP_184912.1| chromosomal replication initiation protein                                                                   %           1        0.0           2296      100.0
gi|269201692|ref|YP_003280961.1| DNA polymerase III subunit beta                                                                       gi|57651110|ref|YP_184913.1| DNA polymerase III subunit beta                                                                              %           1        0.0           1964      100.0

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

gi|269201691|ref|YP_003280960.1| gi|57651109|ref|YP_184912.1| % 1        0.0           2296      100.0
gi|269201694|ref|YP_003280963.1| gi|57651112|ref|YP_184915.1| % 1        0.0           1767      100.0

Приведенный ниже код помогает найти столбцы в каждой строке с шаблоном «ref».

awk '{for (i=1;i<=NF;i++) if ($i ~ /ref/) print $i }'

Любые идеи о том, как сделать то же самое?


person pulikot1    schedule 29.10.2012    source источник
comment
Вы хотите несколько gi и refs в каждой строке вывода? Текст здесь завернут?   -  person amaurea    schedule 29.10.2012
comment
Чтобы избежать переноса строк, просто сделайте отступ в коде четырьмя пробелами. Но я вижу, что ваши строки на самом деле включают в себя две вещи ги. Хорошо, я приму это во внимание и обновлю свой ответ.   -  person amaurea    schedule 29.10.2012
comment
То же, что? Есть много причин, по которым вы могли бы производить этот вывод, расскажите нам, что именно вы отключаете.   -  person Ed Morton    schedule 29.10.2012


Ответы (3)


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

awk -F '[|%]' '{printf("%s|%d|%s|%s|",$1,$2,$3,$4);if($6)printf(" %%%s",$6);printf("\n")}'

Редактировать: хорошо, в свете новых номеров строк, вы, вероятно, хотите это:

awk -F '[|%]' '{printf("gi|%d|ref|%s|gi|%d|ref|%s| %%%s\n",$2,$4,$6,$8,$10)}'

Для вашего примера это дает мне следующий вывод

gi|269201691|ref|YP_003280960.1|gi|57651109|ref|YP_184912.1| % 1 0.0 2296 100.0
gi|269201692|ref|YP_003280961.1|gi|57651110|ref|YP_184913.1| % 1 0.0 1964 100.0

Это работает путем ручной установки разделителя полей | или %. Следовательно, переменное количество слов в описании больше не является проблемой, и мы можем напрямую индексировать нужные нам поля.

person amaurea    schedule 29.10.2012
comment
Спасибо за ответ. Код печатает только первый столбец - person pulikot1; 29.10.2012
comment
Если код не дает вывод, который я опубликовал, то я, вероятно, неправильно понял формат, в котором находятся ваши данные. Не могли бы вы опубликовать правильно отформатированный ввод, отступив каждую строку ввода четырьмя пробелами? Это приведет к форматированию, которое вы видите в моем ответе, и, что особенно важно, строки не будут разорваны. - person amaurea; 29.10.2012
comment
Если это работает, вы должны отметить ответ как принятый, нажав на галочку. Это показывает другим, что вы больше не ищете ответы на этот вопрос. - person amaurea; 29.10.2012

Это может сработать для вас (GNU sed):

sed 's/\(.*|.*|.*|.*|\)\(.*\)\(\S\+|.*|.*|.*|\)\2%/\1\3%/' file

Если входной файл содержит многострочные записи:

sed 'N;s/\n//;s/\(.*|.*|.*|.*|\)\(.*\)\(\S\+|.*|.*|.*|\)\2%/\1\3%/' file
person potong    schedule 29.10.2012

Вот один из способов использования GNU awk:

awk 'BEGIN { OFS=FS="|" } { for (i=1; i<=NF; i++) if ($i ~ / gi$/) $i = " gi"; if (i = NF) sub(/.*%/," %",$i) }1' file.txt

Вот один из способов использования GNU sed:

sed 's/|[^|]* gi|/| gi|/; s/\(.*|\).*\(%.*\)/\1 \2/' file.txt

Полученные результаты:

gi|269201691|ref|YP_003280960.1| gi|57651109|ref|YP_184912.1| % 1 0.0 2296 100.0
gi|269201692|ref|YP_003280961.1| gi|57651110|ref|YP_184913.1| % 1 0.0 1964 100.0
person Steve    schedule 29.10.2012