AWK - usuwanie konkretnej liczby linijek

0

Mam taki skrypt w awk

BEGIN {while (getline < "system_solvate.gro") {if ($1 ~ /SOL/ && $NF > 1.258 && $NF < 5.702) name[$1]=$1}} {if ($1 != name[$1]) print}

Tutaj krótki wycinek danych, na których pracuje

    1BGL     O315983   1.764   1.230  10.527  0.1713 -0.0251 -0.4777
    1BGL    HO315984   1.808   1.314  10.533 -1.1309  0.6737 -0.4894
    1BGL     C415985   1.681   1.308  10.733 -0.5976  0.4021 -0.1961
    1BGL     H415986   1.736   1.232  10.789 -0.1768 -1.1019 -2.5278
    1BGL     O415987   1.771   1.413  10.714 -0.0719 -0.6085 -0.3470
    1BGL    HO415988   1.858   1.396  10.746  0.6547  0.9962 -1.3920
    1BGL     C615989   1.585   1.426  10.941  0.1562 -0.7307 -0.4556
    1BGL    H6115990   1.623   1.528  10.932  1.0402 -1.0742 -0.6533
    1BGL    H6215991   1.650   1.353  10.989  1.5359  1.0359  0.4522
    1BGL     O615992   1.468   1.412  11.021 -0.5619  0.6198 -0.5706
    1BGL    HO615993   1.419   1.491  11.010  0.2171  0.9404 -1.8062
    2GLC     O115994   1.373   1.484  10.534 -0.6423  0.0877  0.1253
    2GLC    H3A16013   1.605   1.375  10.212  1.2105  1.0948 -1.2238
    2GLC    H3B16014   1.569   1.234  10.117  1.9138  0.2155 -1.6127
    3LIN     C316015   1.282   1.037  10.262 -0.0077  0.3221 -0.1453
    3LIN    H3116016   1.381   1.082  10.255 -0.0750  0.3641 -0.9355
    3LIN    H3216017   1.220   1.089  10.189  0.4413 -1.7672 -2.0754
    3LIN     C416018   1.286   0.900  10.200  0.6641 -0.0713 -0.3543
    3LIN    H4116019   1.353   0.838  10.260 -0.0531 -0.2731  0.2467
    3LIN    H4216020   1.188   0.859  10.224  1.2703 -0.7235  1.0673
    5SOL     OW16101   9.191  12.527   0.902  1.6461 -0.1906 -0.4677
    5SOL    HW116102   9.284  12.544   0.887  1.4614  1.5503  0.1395
    5SOL    HW216103   9.162  12.600   0.957 -0.2552 -0.2956 -1.2629
    6SOL     OW16104   0.266   3.581   6.291 -0.0998 -0.2240  0.4797
    6SOL    HW116105   0.211   3.556   6.365  0.5318  0.2074  1.1058
    6SOL    HW216106   0.353   3.593   6.329 -0.1346  1.8066  0.0231
    7SOL     OW16107   6.692   8.043   6.897  0.2346  0.7472 -0.0648
    7SOL    HW116108   6.653   8.100   6.964  0.1092 -1.3848  1.7771
    7SOL    HW216109   6.786   8.048   6.913  0.4205  2.2007 -1.4320
    8SOL     OW16110   0.218  14.041  12.014  0.5025 -0.3016  0.5777
    8SOL    HW116111   0.239  14.016  12.103  1.4617 -1.3916  0.0664
    8SOL    HW216112   0.301  14.068  11.976 -0.0939  1.3637  0.3551

Ogółem tych linijek jest kilkaset tysięcy

Ogólnie rzecz biorąc ten skrypt usuwa wszystkie cząsteczki wody, które znajdują się w koordynacie z od jakiejś do jakiejś wartości (wystarczy, żeby którykolwiek z trzech atomów OW/HW1/HW2) znajdował się w tych koordynatach. Chcę ulepszyć ten skrypt tak aby usuwał, ale tylko określoną liczbę cząsteczek wody w danych koordynatach, np. pomiędzy koordynatami 1.258 i 5.702 znajduje się 6000 cząsteczek wody. Ten skrypt, który obecnie mam usunie mi 6000 cząsteczek wody, ale chciałbym, żeby usunął np. 2000. Czy w awk da się coś takiego zrobić czy będę musiał kombinować i pisać skrypt od nowa w pythonie?

3

Czemu używasz AWK w taki dziwny sposób?

Powolutku:

  • BEGIN niepotrzebne
  • tablica asocjacyjna niepotrzebna
BEGIN { count = 0; }

$1 ~ /SOL$/ && $NF > 1.258 && $NF < 5.702 && count < 2000 {
  count++;
  print;
}

To powinno wystarczyć.

1

Dokładnie, kod jest przekombinowany i nieczytelny. Jak chcesz się nauczyć używać AWK właściwie: http://it.wiedz.net.pl/unix/awk.html

0
hauleth napisał(a):

Czemu używasz AWK w taki dziwny sposób?

Powolutku:

  • BEGIN niepotrzebne
  • tablica asocjacyjna niepotrzebna
BEGIN { count = 0; }

$1 ~ /SOL$/ && $NF > 1.258 && $NF < 5.702 && count < 2000 {
  count++;
  print;
}

To powinno wystarczyć.

Tu jest jeszcze jeden problem, mam przykładowy plik wejściowy
"
57SOL OW30154 0.953 1.699 0.880
57SOL HW130155 1.038 1.654 0.882
57SOL HW230156 0.904 1.654 0.811
58SOL OW30157 0.416 0.672 0.499
58SOL HW130158 0.436 0.578 0.506
58SOL HW230159 0.322 0.678 0.515
59SOL OW30160 0.611 0.121 0.076
59SOL HW130161 0.689 0.083 0.117
59SOL HW230162 0.642 0.149 9.525
"

uruchamiając skrypt

#!/bin/bash
awk 'BEGIN { count = 0; }

$1 ~ /SOL$/ && $NF > 0.801 && $NF < 0.833 && count < 2000 {
  count++;
  print;
}' test1.gro | tee test2.gro

otrzymam
57SOL HW230156 0.904 1.654 0.811

a chciałbym otrzymać
57SOL OW30154 0.953 1.699 0.880
57SOL HW130155 1.038 1.654 0.882
57SOL HW230156 0.904 1.654 0.811

bo w tym pierwszym przypadku zniszczyłem cząsteczkę wody. Wyrzuciłem jeden z atomów i zostało mi samo OH. Ja chcę jak już coś eliminować całą cząsteczkę wody, jeśli którykolwiek z atomów znajdzie się w wyznaczonym zakresie koordynatów z (jeśli któryś z 57SOL wystarczy jeden znajdzie się w tych koordynatach to usuwam wszystkie trzy atomy, jeśli którykolwiek z 58SOL znajdzie się w koordynatach usuwam wszystkie 3 atomy). Jeśli eliminowałbym w ten sposób miałbym sporo pojedynczych atomów wodoru/tlenu lub grup OH, a ja tego nie chce mieć.

Wiesz może jak to udoskonalić?

1

Zwiększaj (count++) tylko dla tlenu, a nie per każdy wpis SOL.

1 użytkowników online, w tym zalogowanych: 0, gości: 1