1
votes

AWK dans une boucle pour créer plusieurs fichiers sous forme de fichiers uniques

J'ai le fichier ci-dessous nommé ABCD.vasp:

for ((i=1;i<=10;i++));do
        outputfile=test"$i".vasp
        awk -v I=$i 'NR > 9 && $3+0 >= 0.25 {
        p = $1; p =($I * 0.025); sub(/[^ \t]+/, sprintf("%.8f", p)) } 1' $inputfile > $outputfile
done

Les opérations que je veux faire sur le fichier ci-dessus:

  1. Je souhaite copier les premières 9 lignes dans un nouveau fichier nommé test.vasp
  2. Numéro de ligne 10 et suivants, si la troisième colonne est > = 0,25 alors la première colonne doit être augmentée de 0,025 et la ligne entière doit être ajouté à test1.vasp
  3. Numéro de ligne 10 et suivants, si la troisième colonne est , alors la ligne entière doit être ajoutée à test1.vasp li >
  4. Étape 2 et Étape 3 Je veux répéter de 0,025 à 0,25 pour test1.vasp à test10.vasp

J'ai essayé la commande ci-dessous qui ne fonctionne pas:

# A B C D
1.000000
     13.85640621        0.00000000        0.00000000
      4.61880236       13.06394496        0.00000000
      0.00000000        0.00000000       45.25483322
A B C D
   32      32      32      32
Selective dynamics
Direct
      0.00000000        0.00000000        0.00000000 F F F
      0.00000000        0.00000000        0.12500000 F F T
      0.00000000        0.00000000        0.25000000 F F T
      0.00000000        0.00000000        0.37500000 F F T
      0.50000000        0.00000000        0.00000000 F F F
      0.50000000        0.00000000        0.12500000 F F T
      0.50000000        0.00000000        0.25000000 F F T
      0.50000000        0.00000000        0.37500000 F F T
      0.12500000        0.37500000        0.06250000 F F T
      0.12500000        0.37500000        0.18750000 F F T
      0.12500000        0.37500000        0.31250000 F F T  

Veuillez suggérer une solution à cela dans awk ou sed


4 commentaires

Pour autant que je comprends votre question, tout va dans le fichier «test.vasp». Alors, comment voulez-vous générer plusieurs fichiers .... quelle est la différence entre tous ces fichiers?


@kvantour J'ai mis à jour la question.


voulez-vous dire que l'incrément change entre 0,025 0,05 0,075 ou les limites?


@kvantour, l'incrément doit être par pas de 0,025. Pour le fichier test1.vasp, l'incrément est 1 * 0,025 = 0,025, pour test2.vasp l'incrément est 2 * 0,025 = 0,050 .... pour test10.vasp l'incrément est 10 * 0,025 = 0,25


4 Réponses :


1
votes

N'appelez pas awk plusieurs fois, écrivez simplement dans plusieurs fichiers de sortie pour chaque ligne dans awk, comme ceci:

{
    c=0
    for (i=0.025; i<=0.25; i+=0.025) {
        print ...whatever... >> ("test" (++c) ".vasp")
    }
}


4 commentaires

Les fractions à l'intérieur de la boucle for ne fonctionnent pas dans BASH, car bash ne peut gérer que des entiers. La question principale est de savoir comment gérer la partie impression de mon code.


Il s'agit d'un script Awk, où vous pouvez utiliser des fractions partout. Stockez-le dans un fichier et exécutez-le avec awk -f file


@Sufyan vous semblez accroché à l'idée d'ajouter une boucle shell en dehors de awk - ne faites pas ça. Appelez simplement awk une fois et utilisez votre code awk existant modifié en boucle comme je le montre.


Oh! J'ai totalement oublié les scripts Awk. Merci, @tripleee



1
votes

pour la section numérique, vous pouvez faire quelque chose comme ceci

$ head *.vasp | column -t

==>         test1.vasp   <==
0.00000000  0.00000000   0.00000000  F  F  F
0.00000000  0.00000000   0.12500000  F  F  T
0.25000000  0.00000000   0.25000000  F  F  T
0.25000000  0.00000000   0.37500000  F  F  T
0.50000000  0.00000000   0.00000000  F  F  F
0.50000000  0.00000000   0.12500000  F  F  T
0.75000000  0.00000000   0.25000000  F  F  T
0.75000000  0.00000000   0.37500000  F  F  T
0.12500000  0.37500000   0.06250000  F  F  T
0.12500000  0.37500000   0.18750000  F  F  T
==>         test10.vasp  <==
0.00000000  0.00000000   0.00000000  F  F  F
0.00000000  0.00000000   0.12500000  F  F  T
2.50000000  0.00000000   0.25000000  F  F  T
2.50000000  0.00000000   0.37500000  F  F  T
0.50000000  0.00000000   0.00000000  F  F  F
0.50000000  0.00000000   0.12500000  F  F  T
3.00000000  0.00000000   0.25000000  F  F  T
3.00000000  0.00000000   0.37500000  F  F  T
0.12500000  0.37500000   0.06250000  F  F  T
0.12500000  0.37500000   0.18750000  F  F  T
==>         test2.vasp   <==
0.00000000  0.00000000   0.00000000  F  F  F
0.00000000  0.00000000   0.12500000  F  F  T
0.50000000  0.00000000   0.25000000  F  F  T
0.50000000  0.00000000   0.37500000  F  F  T
0.50000000  0.00000000   0.00000000  F  F  F
0.50000000  0.00000000   0.12500000  F  F  T
1.00000000  0.00000000   0.25000000  F  F  T
1.00000000  0.00000000   0.37500000  F  F  T
0.12500000  0.37500000   0.06250000  F  F  T
0.12500000  0.37500000   0.18750000  F  F  T
==>         test3.vasp   <==
0.00000000  0.00000000   0.00000000  F  F  F
0.00000000  0.00000000   0.12500000  F  F  T
0.75000000  0.00000000   0.25000000  F  F  T
0.75000000  0.00000000   0.37500000  F  F  T
0.50000000  0.00000000   0.00000000  F  F  F
0.50000000  0.00000000   0.12500000  F  F  T
1.25000000  0.00000000   0.25000000  F  F  T
1.25000000  0.00000000   0.37500000  F  F  T
0.12500000  0.37500000   0.06250000  F  F  T
0.12500000  0.37500000   0.18750000  F  F  T

donnera

$ awk 'NR>9{for(i=1;i<=10;i++)
              {f="test" i ".vasp";
               if($3>=0.25) $1=sprintf("%.8f",$1+0.25)
               print > f}}' file


2 commentaires

J'ai essayé cela, mais cela ne conserve pas les lignes 1 à 8 dans les fichiers de test.


Oui, "pour la section numérique" uniquement comme vous pouvez le voir dans la sortie. Dans votre message, vous avez écrit "Je veux copier les 9 premières lignes dans un nouveau fichier nommé test.vasp" , donc j'ai pensé que la section de données n'incluait pas ces lignes? Sinon, c'est trivial à ajouter. Le format n'est pas non plus conservé.



1
votes

Vous pouvez utiliser ce script awk .

awk -f incr.awk file

Ensuite, exécutez-le comme:

cat incr.awk

NR <= 9 {
   s = s $0 ORS
   next
}
{
   r[++n] = $0
}
END {
   for (i=1; i<=10; i++) {
      fn = "test" i ".vasp"
      printf "%s", s > fn
      for (k=1; k<=n; ++k) {
         split(r[k], a)
         if (a[3] >= 0.25) {
            sub(/[^\t]+/, sprintf("%.8f", a[1] + .025), r[k])
         }
         print r[k] > fn
      }
      close(fn)
   }
}


1 commentaires

J'ai utilisé votre réponse précédente sur stackoverflow.com/a/62556657/12832411 et l'ai légèrement modifiée. Vérifiez ma réponse qui a fonctionné.



-1
votes

De la réponse à ma question précédente: https://stackoverflow.com/a/62556657/12832411

Cela a fonctionné pour moi:

for ((i=1;i<=10;i++));do
   outputfile=test"$i".vasp
   awk -v I=$(( i * 0.025 )) 'NR > 9 && $3+0 >= 0.25 {
   p = $1; p +=I; sub(/[^ \t]+/, sprintf("%.8f", p)) } 1' $inputfile > $outputfile
done


2 commentaires

Ce n'est pas une solution efficace car elle appelle awk 10 fois. Veuillez vérifier ma réponse pour le faire dans une commande awk


Vous avez 3 réponses qui ne font pas cela et plusieurs commentaires vous conseillant de ne pas le faire. Vous voudrez peut-être reconsidérer cela.