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:
9
lignes dans un nouveau fichier nommé test.vasp
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
10
et suivants, si la troisième colonne est , alors la ligne entière doit être ajoutée à test1.vasp
li >
- É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 Réponses :
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") } }
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
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
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é.
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) } }
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é.
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
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.
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