Incrémentation d'une variable à l'intérieur d'une boucle de Bash
j'essaie d'écrire un petit script qui comptera les entrées dans un fichier journal, et j'incrémente une variable (USCOUNTER
) que j'essaie d'utiliser une fois la boucle terminée.
Mais à ce moment USCOUNTER
semble être 0 au lieu de la valeur réelle. Toute idée de ce que je fais mal? Merci!
FILE=
tail -n10 mylog > $FILE
USCOUNTER=0
cat $FILE | while read line; do
country=$(echo "$line" | cut -d' ' -f1)
if [ "US" = "$country" ]; then
USCOUNTER=`expr $USCOUNTER + 1`
echo "US counter $USCOUNTER"
fi
done
echo "final $USCOUNTER"
Il affiche:
US counter 1
US counter 2
US counter 3
..
final 0
8 réponses
Vous utilisez USCOUNTER
dans un sous-coquille, c'est pourquoi la variable n'apparaît pas dans la coquille principale.
au Lieu de cat FILE | while ...
, est-ce juste un while ... done < $FILE
. De cette façon, vous évitez le problème commun de la je mets des variables dans une boucle qui est dans un pipeline. Pourquoi disparaissent-ils après la boucle? Ou, pourquoi je ne peux pas Piper des données pour lire?:
while read country _; do
if [ "US" = "$country" ]; then
USCOUNTER=$(expr $USCOUNTER + 1)
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Note j'ai aussi remplacé l'expression " par $().
j'ai aussi remplacé while read line; do country=$(echo "$line" | cut -d' ' -f1)
while read country _
. Ceci permet de dire while read var1 var2 ... varN
où var1
contient le premier mot de la ligne, $var2
et ainsi de suite, jusqu'à ce que $varN
contenant le reste du contenu.
Toujours utiliser -r
à lire. Aussi il n'est pas nécessaire d'utiliser cut
, Vous pouvez vous en tenir à des solutions de bash pures
Préférez [[ ]]
[ ]
Utiliser des expressions arithmétiques
n'oubliez pas de citer les variables! Lien inclut d'autres pièges
while read -r country _; do
if [[ $country = 'US' ]]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Vous obtenez final 0
parce que votre while loop
est exécuté dans un processus sub (shell) et tout changement y apporté n'est pas reflété dans le shell actuel (parent).
Correct script:
while read -r country _; do
if [ "US" = "$country" ]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
j'ai eu la même variable $count dans une boucle de temps se perdre problème.
la réponse de@fedorqui (et quelques autres) sont des réponses précises à la question: le sous-shell est bien le problème.
mais ça m'a mené à un autre problème: Je ne pipais pas le contenu d'un fichier... mais la sortie d'une série de pipes et grep...
mon erroring exemple de code:
count=0
cat /etc/hosts | head | while read line; do
((count++))
echo $count $line
done
echo $count
et mon corrigé grâce à l'aide de ce fil et le processus la substitution:
count=0
while IFS= read -r line; do
((count++))
echo "$count $line"
done < <(cat /etc/hosts | head)
echo "$count"
Incrémentation d'une variable qui peut être fait comme ça:
_my_counter=$[$_my_counter + 1]
pour compter le nombre d'occurrence d'un motif dans une colonne peut être fait avec grep
grep -cE "^([^ ]* ){2}US"
-c
count
([^ ]* )
Pour détecter une colonne
{2}
la colonne nombre
US
votre profil
en utilisant la commande suivante d'une ligne pour changer le nom de nombreux fichiers dans linux en utilisant la spécificité de phrase:
find -type f -name '*.jpg' | rename 's/holiday/honeymoon/'
Pour tous les fichiers avec l'extension ".jpg", s'ils contiennent la chaîne de caractères "holiday", remplacez-la par "honeymoon". Par exemple, cette commande renommerait le fichier "ourholiday001."jpg" à "ourhoneymoon001.jpg".
Cet exemple montre également comment utiliser la commande rechercher pour envoyer une liste de fichiers (type f) avec l'extension .jpg (- name'*.jpg') à renommer via une pipe ( / ). renommer lit ensuite sa liste de fichiers à partir de l'entrée standard.