J'ai ce script bash et j'ai eu un problème à la ligne 16. Comment puis-je prendre le résultat précédent de la ligne 15 et l'ajouter à la variable de la ligne 16?
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
num= $num + $metab (line16)
done
echo "$num"
done
Pour les entiers :
Utilisez expansion arithmétique : $((EXPR))
num=$((num1 + num2))
num=$(($num1 + $num2)) # also works
num=$((num1 + 2 + 3)) # ...
num=$[num1+num2] # old, deprecated arithmetic expression syntax
Utilisation de l'utilitaire externe expr
. Notez que cela n’est nécessaire que pour les systèmes très anciens.
num=`expr $num1 + $num2` # whitespace for expr is important
Pour la virgule flottante :
Bash ne supporte pas directement cela, mais il y a quelques outils externes que vous pouvez utiliser:
num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(Perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc) # whitespace for echo is important
Vous pouvez également utiliser la notation scientifique (par exemple: 2.5e+2
)
Pièges courants :
Lorsque vous définissez une variable, vous ne pouvez pas utiliser d'espaces de part et d'autre de =
, sinon le Shell sera obligé d'interpréter le premier mot comme nom de l'application à exécuter (par exemple: num=
ou num
)
num= 1
num =2
bc
et expr
attendent chaque numéro et chaque opérateur comme argument séparé. Les espaces sont donc importants. Ils ne peuvent pas traiter des arguments tels que 3+
+4
.
num=`expr $num1+ $num2`
Utilisez le développement arithmétique $(( ))
.
num=$(( $num + $metab ))
Voir http://tldp.org/LDP/abs/html/arithexp.html pour plus d'informations.
Il y a mille et une façons de le faire. En voici une qui utilise dc
:
dc <<<"$num1 $num2 + p"
Mais si c'est trop bas pour vous (ou que la portabilité compte), vous pourriez dire
echo $num1 $num2 + p | dc
Mais peut-être êtes-vous de ceux qui pensent que RPN est dégoûtant et étrange; ne t'inquiète pas! bc
est là pour vous:
bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc
Cela dit, vous pourriez apporter des améliorations indépendantes à votre script.
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in output-$i-* ; do # for can glob directly, no need to ls
echo "$j"
# grep can read files, no need to use cat
metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
num=$(( $num + $metab ))
done
echo "$num"
done
MODIFIER:
Comme décrit dans BASH FAQ 022 , bash ne supporte pas nativement les nombres à virgule flottante. Si vous devez additionner des nombres en virgule flottante, l'utilisation d'un outil externe (tel que bc
ou dc
) est requise.
Dans ce cas, la solution serait
num=$(dc <<<"$num $metab + p")
Pour additionner des nombres à virgule flottante dans num
.
En bash,
num=5
x=6
(( num += x ))
echo $num # ==> 11
Notez que bash ne peut gérer que l'arithmétique entière, donc si votre commande awk retourne une fraction, vous voudrez la refondre: voici votre code un peu réécrit pour faire tous les calculs dans awk.
num=0
for ((i=1; i<=2; i++)); do
for j in output-$i-*; do
echo "$j"
num=$(
awk -v n="$num" '
/EndBuffer/ {sum += $2}
END {print n + (sum/120)}
' "$j"
)
done
echo "$num"
done
J'oublie toujours la syntaxe alors je viens sur Google, mais je ne trouve jamais celle que je connais bien: P. C’est le plus propre et le plus fidèle à ce que j’attendais dans d’autres langues.
i=0
((i++))
echo $i;
J'aime aussi beaucoup cette méthode, moins d'encombrement:
count=$[count+1]
#!/bin/bash
read X
read Y
echo "$(($X+$Y))"
Vous devez déclarer la métab comme un entier, puis utiliser l'évaluation arithmétique.
declare -i metab num
...
num+=metab
...
Pour plus d'informations, voir https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic
Une autre manière portable POSIX
conforme à faire dans bash
, qui peut être définie comme une fonction dans .bashrc
pour tous les opérateurs arithmétiques de convenance.
addNumbers () {
local IFS='+'
printf "%s\n" "$(( $* ))"
}
et appelez-le simplement en ligne de commande en tant que,
addNumbers 1 2 3 4 5 100
115
L'idée est d'utiliser Input-Field-Separator (IFS) , une variable spéciale dans bash
utilisée pour la division de Word après le développement et la division de lignes en mots. La fonction modifie la valeur localement pour utiliser le caractère de fractionnement de Word comme opérateur de somme +
.
Rappelez-vous que IFS
est modifié localement et ne PAS prend effet sur le comportement par défaut IFS
en dehors de la portée de la fonction. Un extrait de la page man bash
,
Le shell traite chaque caractère de l’IFS comme un séparateur et divise les résultats des autres extensions en mots sur ces caractères. Si IFS n'est pas défini ou si sa valeur est exactement la valeur par défaut, les séquences de, et au début et à la fin des résultats des extensions précédentes sont ignorées, et toute séquence de caractères IFS ne figurant pas au début ou à la fin sert à délimiter mots.
"$(( $* ))"
représente la liste des arguments passés pour être scindés par +
, puis la valeur de somme est sortie à l'aide de la fonction printf
. La fonction peut être étendue pour ajouter également une portée pour d'autres opérations arithmétiques.
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
let num=num+metab (line 16)
done
echo "$num"
done