Позиционная замена блока текста, если строка совпадает в той же строке - PullRequest
2 голосов
/ 28 ноября 2011

У меня есть два набора файлов PDB (это стандартный формат, который нельзя изменить). Первый набор как:

ATOM     18  C33 Q58 d  91     -25.677   3.886 -30.044  1.00  0.00           C  
ATOM     19  C34 Q58 d  91     -24.704   4.881 -29.447  1.00  0.00           C  
ATOM     20  C35 Q58 d  91     -23.382   4.873 -30.182  1.00  0.00           C  
ATOM     21  C8  Q58 d  91     -20.295  11.484 -33.616  1.00  0.00           C  
ATOM     22  C7  Q58 d  91     -19.198  12.305 -33.381  1.00  0.00           C  
ATOM     23  C3  Q58 d  91     -18.213  12.498 -34.383  1.00  0.00           C   

А второй идет:

HETATM 2686  C7  589 A   1     -19.344  12.177 -33.319  1.00 25.88           C  
HETATM 2687  C8  589 A   1     -20.388  11.319 -33.511  1.00 26.31           C  
HETATM 2688  C9  589 A   1     -20.364  10.691 -34.747  1.00 26.14           C  
HETATM 2689  C10 589 A   1     -19.402  10.845 -35.729  1.00 26.34           C  
HETATM 2690  N11 589 A   1     -21.334  11.123 -32.604  1.00 26.22           N  
HETATM 2691  C12 589 A   1     -21.713   9.967 -32.081  1.00 25.65           C  

Каждый столбец разделен переменным количеством пробелов, так что его содержимое занимает определенный позиционный диапазон.

Столбцы 7-9 представляют координаты x, y, z в декартовом пространстве. Я хотел бы заменить координаты файла 2 координатами из файла 1 для всех совпадений столбца 3 (тип атома).

Например, в примере выходной файл 2 будет:

HETATM 2686  C7  589 A   1     -19.198  12.305 -33.381  1.00 25.88           C  
HETATM 2687  C8  589 A   1     -20.295  11.484 -33.616  1.00 26.31           C  
HETATM 2688  C9  589 A   1     -20.364  10.691 -34.747  1.00 26.14           C  
HETATM 2689  C10 589 A   1     -19.402  10.845 -35.729  1.00 26.34           C  
HETATM 2690  N11 589 A   1     -21.334  11.123 -32.604  1.00 26.22           N  
HETATM 2691  C12 589 A   1     -21.713   9.967 -32.081  1.00 25.65           C  

Обратите внимание, как изменились координаты первых двух строк (атомы C7 и C8).

Я пробовал awk, но он кажется слишком зависимым от разделителя, что не очень хорошо в этом примере. Столбец 3 (тип атома) всегда находится в позициях 14-16, тогда как 3 координатных столбца охватывают от 32 до 54.

ПРИМЕЧАНИЕ. В некоторых случаях некоторые столбцы могут объединяться. Например, в этом примере столбцы 5 и 6 объединены (это также может произойти со столбцами 1 и 2):

HETATM 2804  PG  ANP A1001      23.808  17.953  28.350  1.00 52.23           P  

Мое РЕШЕНИЕ далеко (медленно, но работает):

while read line ; do
atom=$(echo "$line" | cut -c13-16)
coord=$(grep -i "$atom" ${ligand}_${chain}_dock.tmp | cut -c32-54)
echo "$line" | sed -r "s/^(.{31})(.{23})/\1${coord}/" >> ${ligand}_${chain}_dock.pdb
done < ${ligand}_${chain}_ref.pdb

Ответы [ 3 ]

3 голосов
/ 28 ноября 2011

Я, наверное, выбрал глупый способ ее решить: играть с оператором printf. однако это работает для вашего примера.

Команда:

 awk -F' *' 'NR==FNR{a[$3]=$7;b[$3]=$8;c[$3]=$9;next;}\
{if($3 in a)printf "%s %s  %-3s %s %s %3s %11s %7s %7s %5s %s %11s\n",\
        $1,$2,$3,$4,$5,$6,a[$3],b[$3],c[$3],$10,$11,$12; else print $0}' file1 file2

тест на вашем примере:

kent$  awk -F' *' 'NR==FNR{a[$3]=$7;b[$3]=$8;c[$3]=$9;next;}
{if($3 in a)printf "%s %s  %-3s %s %s %3s %11s %7s %7s %5s %s %11s\n",
        $1,$2,$3,$4,$5,$6,a[$3],b[$3],c[$3],$10,$11,$12; else print $0}' file1 file2
HETATM 2686  C7  589 A   1     -19.198  12.305 -33.381  1.00 25.88           C
HETATM 2687  C8  589 A   1     -20.295  11.484 -33.616  1.00 26.31           C
HETATM 2688  C9  589 A   1     -20.364  10.691 -34.747  1.00 26.14           C  
HETATM 2689  C10 589 A   1     -19.402  10.845 -35.729  1.00 26.34           C  
HETATM 2690  N11 589 A   1     -21.334  11.123 -32.604  1.00 26.22           N  
HETATM 2691  C12 589 A   1     -21.713   9.967 -32.081  1.00 25.65           C 
1 голос
/ 28 ноября 2011

Я угадал правильную ширину поля, но это должно сработать, если они настроены правильно.

#!/usr/bin/env bash

file1="$1"
file2="$2"

fw=(7 6 4 4 4 6 9 7 9 5 16 4)

while IFS= read -r -a f2_line ; do
    let pos=0
    f2_fields=()
    for width in "${fw[@]}" ; do
            f2_fields=("${f2_fields[@]}" "${f2_line:${pos}:${width}}")
            let pos+=width
    done

    printf '%s' "${f2_fields[@]:0:6}"
    orig=1
    while IFS= read -r -a f1_line ; do
            let pos=0
            f1_fields=()
            for width in "${fw[@]}" ; do
                    f1_fields=("${f1_fields[@]}" "${f1_line:${pos}:${width}}")
                    let pos+=width
            done
            if [ "${f1_fields[2]}" = "${f2_fields[2]}" ] ; then
                    orig=
                    printf '%s' "${f1_fields[@]:6:3}"
                    break
            fi
    done < "$file1"
    if [ ! -z "$orig" ] ; then
            printf '%s' "${f2_fields[@]:6:3}"
    fi
    printf '%s' "${f2_fields[@]:9}"
    printf '\n'
done < "$file2"

Это, конечно, не очень эффективно.

РЕДАКТИРОВАТЬ: К сожалению, пришлось s / 5/6 / в строке 14. Работает сейчас.

0 голосов
/ 28 ноября 2011

Это бы тоже сработало. Вместо того, чтобы печатать каждый столбец, мы устанавливаем переменную OFS в «\ t».

ОБНОВЛЕНИЕ: Добавлено несколько пробелов рядом с символом табуляции в переменной OFS. Это дает вашему выходу достаточное расстояние между собой.

[jaypal:~/Temp]  awk -v OFS="\t    " 'NR==FNR{a[$3]=$7;b[$3]=$8;c[$3]=$9;next} ($3 in a) {$7=a[$3];$8=b[$3];$9=c[$3];print $0;next} {$1=$1}1' file1 file2
HETATM      2686        C7      589     A       1       -19.198     12.305      -33.381     1.00        25.88       C
HETATM      2687        C8      589     A       1       -20.295     11.484      -33.616     1.00        26.31       C
HETATM      2688        C9      589     A       1       -20.364     10.691      -34.747     1.00        26.14       C
HETATM      2689        C10     589     A       1       -19.402     10.845      -35.729     1.00        26.34       C
HETATM      2690        N11     589     A       1       -21.334     11.123      -32.604     1.00        26.22       N
HETATM      2691        C12     589     A       1       -21.713     9.967       -32.081     1.00        25.65       C
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...