#1 Le 23/01/2012, à 14:20
- compte supprimé
[Résolu] Bash soustraction en boucle
Bonjour la communauté
J'ai le fichier "fichier.txt" contenant ça comme donné :
0
80
300
600
1000
1500
2200
J'aimerais faire ceci, prendre la valeur de la 2ème ligne moins la valeur de la 1er ligne
valeur 3ème ligne - valeur 2ème ligne
valeur 4ème ligne - valeur 3ème ligne
...
Jusqu'à la fin du fichier.
J'ai trouver un début de réponse pour la première opération mais c'est là que je bloque car il faudrait crée une boucle... pour continué jusqu'au dernière ligne mais comment ???
echo "scale=2; $(cat fichier.txt | awk 'NR==2 {print $1}') - $(cat fichier.txt | awk 'NR==1 {print $1}')" | bc
Dernière modification par Orion79 (Le 04/03/2012, à 13:13)
#2 Le 23/01/2012, à 14:41
- pingouinux
Re : [Résolu] Bash soustraction en boucle
Bonjour,
Ceci devrait convenir :
awk '{n[NR]=$0}END{for(i=1;i<NR;i++){printf("%d\n",n[i+1]-n[i])}}' fichier.txt
Autre suggestion, moins élégante :
dc <(paste <(tail -n +2 fichier.txt) <(head -n -1 fichier.txt) | sed 's/$/ -p/')
Encore une autre :
awk '{for(i=1;i<NF;i++){printf("%d\n",$(i+1)-$i)}}' <<<$(cat fichier.txt)
Dernière modification par pingouinux (Le 23/01/2012, à 14:59)
Hors ligne
#3 Le 23/01/2012, à 15:13
- sputnick
Re : [Résolu] Bash soustraction en boucle
Ton titre est contradictoire avec ta description !
S'agit-il d'addition ou de soustraction ? oO
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#4 Le 23/01/2012, à 15:34
- Watael
Re : [Résolu] Bash soustraction en boucle
salut,
tant qu'on reste dans les entiers, il n'y a aucune raison d'utiliser un programme externe.
le shell s'en débrouille très bien.
quelle doit-être la sortie du script?
Dernière modification par Watael (Le 23/01/2012, à 15:35)
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#5 Le 23/01/2012, à 15:41
- credenhill
Re : [Résolu] Bash soustraction en boucle
hello
$ awk 'NR > 1{print $0-x} {x=$0}' fichier.txt
80
220
300
400
500
700
$
Hors ligne
#6 Le 23/01/2012, à 17:24
- compte supprimé
Re : [Résolu] Bash soustraction en boucle
Ton titre est contradictoire avec ta description !
S'agit-il d'addition ou de soustraction ? oO
C'est corrigé ! Merci de la remarque...
Dernière modification par Orion79 (Le 23/01/2012, à 20:30)
#7 Le 23/01/2012, à 21:00
- compte supprimé
Re : [Résolu] Bash soustraction en boucle
Merci à vous 2 pour vos solutions qui fonctionnent toutes !
Cependant étant curieux par nature j'essaye de comprendre cette commande :
awk 'NR>1 {print $0-x} {x=$0}' fichier.txt
NR > 1 lignes 1 et suivante (jusqu'à la dernière)
{print $0-x} {x=$0} là je ne saisi pas tout ?
#8 Le 23/01/2012, à 21:11
- sputnick
Re : [Résolu] Bash soustraction en boucle
{print $0-x} : afficher la ligne courante - la valeur de la variable x
{x=$0} : stocke la valeur de la ligne courante
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#9 Le 23/01/2012, à 21:18
- sputnick
Re : [Résolu] Bash soustraction en boucle
Ou encore en pure bash :
$ cat /tmp/a
0
80
300
600
1000
1500
2200
$ while read a; do v=$((a - x)); ((v>0)) && echo $v; x=$a; done < /tmp/a
80
220
300
400
500
700
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#10 Le 24/01/2012, à 09:39
- credenhill
Re : [Résolu] Bash soustraction en boucle
NR > 1 lignes 1 et suivante (jusqu'à la dernière)?
ligne 2 et suivantes, NR commence à 1, pas à 0 comme les tableaux, donc le premier bloc {} n'est pas exécuté pour la ligne 1
edit : autre méthode pure bash
$ t=($(<fichier.tt));for x in $(seq 1 $((${#t[@]}-1))) ; do echo $((${t[$x]}-${t[$(($x-1))]})) ; done
80
220
300
400
500
700
$
Dernière modification par credenhill (Le 24/01/2012, à 12:21)
Hors ligne
#11 Le 24/01/2012, à 13:04
- Watael
Re : [Résolu] Bash soustraction en boucle
désolé credenhill, `seq' n'est pas une commande bash.
pour être pur bash
for (( x=0; x<${#t[@]}; x++)); do echo $((${t[x]}-${t[x-1]})) ; done
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#12 Le 24/01/2012, à 13:27
- credenhill
Re : [Résolu] Bash soustraction en boucle
juste !!, mais il faut for (( x=1; x<${#t[@]}; x++));.......
ou
$ t=($(<a3));for x in $(eval echo {1..$((${#t[@]}-1))}) ; do echo $((${t[x]}-${t[x-1]})) ; done
80
220
300
400
500
700
$
Dernière modification par credenhill (Le 24/01/2012, à 13:38)
Hors ligne
#13 Le 24/01/2012, à 14:14
- Watael
Re : [Résolu] Bash soustraction en boucle
bien sûr x=1
mais avec `eval', c'est moche.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#14 Le 24/01/2012, à 15:18
- credenhill
Re : [Résolu] Bash soustraction en boucle
oui, oui, le for ( (...)) est fait pour ça
Hors ligne
#15 Le 24/01/2012, à 17:21
- sputnick
Re : [Résolu] Bash soustraction en boucle
Ceci est en pure bash, plus simple que vos dernières solutions, plus court et surtout plus lisible
$ cat f
0
80
300
600
1000
1500
2200
$ c=0; while read a; do ((c++)); ((c==1)) && continue || echo $((a - x)); x=$a; done < f
80
220
300
400
500
700
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#16 Le 24/01/2012, à 19:22
- compte supprimé
Re : [Résolu] Bash soustraction en boucle
Awk c'est pas du "pur" bash ?
Pourtant de toute les solutions proposées cela est la plus simple...
awk 'NR>1 {print $0-x} {x=$0}' fichier.txt
#17 Le 24/01/2012, à 21:05
- sputnick
Re : [Résolu] Bash soustraction en boucle
Non, awk c'est du pur awk ;p (awk c'est presque un langage de programmation, tout comme bash)
Mais cette solution est effectivement la plus courte et la plus pertinente, comme ça tu a le choix et ça peux intéresser les puristes de bash pour les autres solutions.
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#18 Le 24/01/2012, à 21:35
- aduxas
Re : [Résolu] Bash soustraction en boucle
Mais cette solution est effectivement la plus courte et la plus pertinente, comme ça tu a le choix et ça peux intéresser les puristes de bash pour les autres solutions.
C'est le cas de le dire. Sur un fichier de 61000 lignes, awk met 0.15 secondes. Les puristes attendront 21 secondes.
Hors ligne
#19 Le 24/01/2012, à 21:48
- sputnick
Re : [Résolu] Bash soustraction en boucle
Il est parfois plus pertinent de comprendre ce qu'on fait et utiliser bash que d'être rapide à tout prix (pour la maintenance par exemple) avec des technos obscures comme Awk, C, Perl. Ça dépends du contexte
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#20 Le 24/01/2012, à 22:15
- Totor
Re : [Résolu] Bash soustraction en boucle
d'autres approches :
set -- $(<f)
for entier; do [[ $old ]] && echo $(( entier - old )); old=$entier;done
fi=( $(<f) )
for index in ${!fi[@]}; do ((index)) && echo $((fi[index] - fi[index-1])); done
edit : certaines syntaxes de bash sont également obscures ....
Dernière modification par Totor (Le 24/01/2012, à 22:15)
-- Lucid Lynx --
Hors ligne
#21 Le 24/01/2012, à 22:37
- aduxas
Re : [Résolu] Bash soustraction en boucle
edit : certaines syntaxes de bash sont également obscures ....
Je n'osais pas le dire
Hors ligne
#22 Le 24/01/2012, à 23:02
- sputnick
Re : [Résolu] Bash soustraction en boucle
Ce que je voulait dire c'est que c'est plus facile en bash de faire qq chose de lisible.
Bien sur qu'on peux "obfuscate" du bash
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne
#23 Le 25/01/2012, à 09:57
- credenhill
Re : [Résolu] Bash soustraction en boucle
variation sur le code de spoutnick au #15
$ c=0; while read a; do ((c++)) && echo $((a - x)); x=$a; done < fichier.txt
80
220
300
400
500
700
$
Dernière modification par credenhill (Le 25/01/2012, à 09:57)
Hors ligne
#24 Le 25/01/2012, à 12:58
- compte supprimé
Re : [Résolu] Bash soustraction en boucle
variation sur le code de spoutnick au #15
$ c=0; while read a; do ((c++)) && echo $((a - x)); x=$a; done < fichier.txt 80 220 300 400 500 700 $
Ça ressemble beaucoup à cette commande :
awk 'NR>1 {print $0-x} {x=$0}' fichier.txt
Mais avec l'avantage d'être du "pur" bash, comme ça tout le monde sera content .
#25 Le 25/01/2012, à 23:33
- sputnick
Re : [Résolu] Bash soustraction en boucle
Orion79, c'est que credenhill a réussit à optimiser ma ligne de commande de façon subtile
En fait, 0 dans un contexte arithmétique est faux (au sens de la logique booléenne)
Bravo credenhill, bien ouèj
On ne peut pas mettre d'array dans un string!
https://sputnick.fr/
Hors ligne