2015-03-24 4 views
0

У меня есть большие текстовые файлы, как важные входы, выглядит какУдалить столбцы с помощью команды оболочки

# USER_IP: 37.1.62.12 INTERFACE CHARMM-GUI 
@<TRIPOS>MOLECULE 
lig.pdb 
54 56 1 0 0 
SMALL 
NO_CHARGES 


@<TRIPOS>ATOM 
     1 CAA   2.9880 0.1910 12.9830 C.3  1 P0G 0.0000 
     2 CAB   1.3730 1.7370 10.6500 C.3  1 P0G 0.0000 
     3 CAC  -0.5820 0.2000 10.5350 C.3  1 P0G 0.0000 
     4 OAD  -5.1220 5.7850 8.9220 O.2  1 P0G 0.0000 
     5 OAE  -2.7610 6.1960 4.9010 O.3  1 P0G 0.0000 
     6 OAF  -0.8620 0.4430 6.3540 O.3  1 P0G 0.0000 
     7 CAG   0.7160 -2.5530 14.2490 C.ar  1 P0G 0.0000 
     8 CAH   0.1300 -3.0010 13.0720 C.ar  1 P0G 0.0000 

...

here in each of file I have a lot of strings: 
     6 OAF  -0.8620 0.4430 6.3540 O.3  1 P0G 0.0000 
     7 CAG   0.7160 -2.5530 14.2490 C.ar  1 P0G 0.0000 
     8 CAH   0.1300 -3.0010 13.0720 C.ar  1 P0G 0.0000 

моя задача использует какой-то скрипт Linux и сочетание АФК, SED для удаления всех столбцов из этих фрагментов, за исключением первых 1-5 столбцов, которые имеют для меня значение. Таким образом, пример файла после его обработки должен быть как

# USER_IP: 37.1.62.12 INTERFACE CHARMM-GUI 
@<TRIPOS>MOLECULE 
lig.pdb 
54 56 1 0 0 
SMALL 
NO_CHARGES 


@<TRIPOS>ATOM 
     1 CAA   2.9880 0.1910 12.9830 
     2 CAB   1.3730 1.7370 10.6500 
     3 CAC  -0.5820 0.2000 10.5350 
     4 OAD  -5.1220 5.7850 8.9220 
     5 OAE  -2.7610 6.1960 4.9010 
     6 OAF  -0.8620 0.4430 6.3540 
     7 CAG   0.7160 -2.5530 14.2490 
     8 CAH   0.1300 -3.0010 13.0720 

проблема здесь всегда в одном типе файлов У меня есть несколько строк (его количество может отличаться) до тех сегментов, которые должны быть обработаны. Таким образом, только идея состоит в том, чтобы использовать ниже строки

@<TRIPOS>ATOM 

в качестве эталона и начинает отсчитывать строки столбцы, которые должны быть обработаны только после этой контрольной строки

Я был бы благодарен за несколько примеров, и его краткого объяснения

Глеб

ответ

3

С GNU AWK 4.0 или более поздней версии:

gawk 'flag { split($0, f, " ", d); for(i = 1; i <= 5; ++i) printf("%s%s", d[i - 1], f[i]); print ""; next } /@<TRIPOS>ATOM/ { flag = 1 } 1' filename 

Большая часть этого заключается в том, чтобы сохранить форматирование неповрежденным; если форматирование не имеет значения, то

awk 'flag { NF = 5 } /@<TRIPOS>ATOM/ { flag = 1 } 1' filename 

является более простым способом, который работает со старым простаком и Мок, а также. Для того, чтобы сделать эту работу с BSD AWK,

awk 'flag { NF = 5; $1 = $1 } /@<TRIPOS>ATOM/ { flag = 1 } 1' filename 

необходимо ($1 = $1 только, чтобы заставить восстановление линии). Спасибо @tripleee за комментирование этого.

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

flag {        # if we're already processing lines 
    split($0, f, " ", d)    # split line into array f, save delimiters 
            # into array d 

    for(i = 1; i <= 5; ++i) {   # print the first five fields separated 
    printf("%s%s", d[i - 1], f[i]) # by the saved delimiters 
    } 
    print ""       # add newline 
    next        # that is all. 
} 
            # if we're not processing lines yet 
/@<TRIPOS>ATOM/ { flag = 1 }  # check if we should, and if so set flag 
1         # then print line unchanged. 

Добавление: Другой способ, который также сохраняет форматирование является использование СЭД:

sed '1,/@<TRIPOS>ATOM/ ! { s/\b[[:space:]]/\n/5; s/\n.*//; }' filename 

То есть:

1,/@<TRIPOS>ATOM/ ! {  # For those lines that are not in the range from 
          # the beginning to the first line containing 
          # @<TRIPOS>ATOM 

    s/\b[[:space:]]/\n/5 # place a newline after the fifth column 
    s/\n.*//    # then remove the newline and everything after it 
} 

Это должно работать как с GNU sed, так и с BSD sed. Поскольку \b не является частью основных POSIX регулярных выражений, хотя, более эзотерический SEDS может потребоваться небольшое изменение:

sed '1,/@<TRIPOS>ATOM/ ! { s/\([^[:space:]]\)[[:space:]]/\1\n/5; s/\n.*//; }' filename 

Это работает практически так же, но использует другое регулярное выражение распознать конец столбцов.

+0

Я не был успешно с установкой 'NF = 5' на OS X awk. Было бы неплохо, если бы это сработало, но, похоже, оно не работает портативно. – tripleee

+0

Работает ли он, если вы установили 'NF = 5' и' $ 1 = $ 1'? Я подозреваю, что перестройка строки не запускается в BSD awk, просто установив «NF», но мы действительно хотим установить «NF», чтобы избежать лишних разделителей полей в конце вывода. – Wintermute

+0

Да, это работает. Острота! – tripleee

-1

должны работать:

sed -n '/@<TRIPOS>ATOM/,$p' filename | tail -n +2 | tr -s " " | cut -d" " -f1-5 

Работы следующим образом:

  1. Печати только линии после @<TRIPOS>ATOM:

    sed -n '/@<TRIPOS>ATOM/,$p' filename 
    
  2. опускает первую линию (которая содержит @<TRIPOS>ATOM, и вы этого не хотите):

    tail -n +2 
    
  3. выжимать дополнительные пространства между колоннами:

    tr -s " " 
    
  4. cut столбцы, используя пространство в качестве разделителя, захватить поля, нужно:

    cut -d" " -f1-5 
    
+0

-One Это полностью удаляет заголовок. Заголовок должен быть сохранен, а столбцы настроены только после строки «tripos». – tripleee

Смежные вопросы