linux - programas - scripts bash ejemplos
El incremento del contador en el bucle Bash no funciona (10)
Tengo el siguiente script simple en el que estoy ejecutando un ciclo y quiero mantener un COUNTER
. No puedo entender por qué el contador no se está actualizando. ¿Es debido a la subshell que se está creando? ¿Cómo puedo solucionar esto?
#!/bin/bash
WFY_PATH=/var/log/nginx
WFY_FILE=error.log
COUNTER=0
grep ''GET /log_'' $WFY_PATH/$WFY_FILE | grep ''upstream timed out'' | awk -F '', '' ''{print $2,$4,$0}'' | awk ''{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}'' | awk -F ''&end=1'' ''{print $1"&end=1"}'' |
(
while read WFY_URL
do
echo $WFY_URL #Some more action
COUNTER=$((COUNTER+1))
done
)
echo $COUNTER # output = 0
Creo que este single awk call es equivalente a grep|grep|awk|awk
pipeline: por favor, pruébelo. Su último comando awk parece no cambiar nada en absoluto.
El problema con COUNTER es que el ciclo while se está ejecutando en una subcadena, por lo que cualquier cambio en la variable desaparecerá cuando la subshell se cierre. Necesita acceder al valor de COUNTER en esa misma subcadena. O tome el consejo de @DennisWilliamson, utilice una sustitución de proceso y evite por completo la subshell.
awk ''
/GET //log_/ && /upstream timed out/ {
split($0, a, ", ")
split(a[2] FS a[4] FS $0, b)
print "http://example.com" b[5] "&ip=" b[2] "&date=" b[7] "&time=" b[8] "&end=1"
}
'' | {
while read WFY_URL
do
echo $WFY_URL #Some more action
(( COUNTER++ ))
done
echo $COUNTER
}
En lugar de utilizar un archivo temporal, puede evitar la creación de una subcadena en el ciclo while utilizando la sustitución de proceso.
while ...
do
...
done < <(grep ...)
Por cierto, deberías poder transformar todo ese grep, grep, awk, awk, awk
en un solo awk
.
Esto es todo lo que necesitas hacer:
$((COUNTER++))
Aquí hay un extracto de Learning the bash Shell , 3rd Edition, pp. 147, 148:
Las expresiones aritméticas bash son equivalentes a sus contrapartidas en los lenguajes Java y C. [9] La precedencia y la asociatividad son las mismas que en C. La tabla 6-2 muestra los operadores aritméticos que son compatibles. Aunque algunos de estos son (o contienen) caracteres especiales, no hay necesidad de barras diagonales-escapar de ellos, porque están dentro de la sintaxis $ ((...)).
..........................
Los operadores ++ y - son útiles cuando desea incrementar o disminuir un valor por uno. [11] Funcionan igual que en Java y C, por ejemplo, value ++ incrementa el valor en 1. Esto se denomina incremento posterior ; también hay un incremento previo : valor ++. La diferencia se vuelve evidente con un ejemplo:
$ i=0
$ echo $i
0
$ echo $((i++))
0
$ echo $i
1
$ echo $((++i))
2
$ echo $i
2
Ver http://www.safaribooksonline.com/a/learning-the-bash/7572399/
Parece que no actualizaste el counter
es el script, usa counter++
Primero, no estás aumentando el contador. Cambiar COUNTER=$((COUNTER))
en COUNTER=$((COUNTER + 1))
o COUNTER=$[COUNTER + 1]
lo aumentará.
En segundo lugar, es más complicado propagar hacia atrás las variables de subcadena al destinatario de la llamada como supones. Las variables en una subcadena no están disponibles fuera de la subcadena. Estas son variables locales al proceso hijo.
Una forma de resolverlo es usar un archivo temporal para almacenar el valor intermedio:
TEMPFILE=/tmp/$$.tmp
echo 0 > $TEMPFILE
# Loop goes here
# Fetch the value and increase it
COUNTER=$[$(cat $TEMPFILE) + 1]
# Store the new value
echo $COUNTER > $TEMPFILE
# Loop done, script done, delete the file
unlink $TEMPFILE
Tratar de usar
COUNTER=$((COUNTER+1))
en lugar de
COUNTER=$((COUNTER))
minimalista
counter=0
((counter++))
echo $counter
COUNTER=$((COUNTER+1))
es una construcción bastante torpe en la programación moderna.
(( COUNTER++ ))
se ve más "moderno". También puedes usar
let COUNTER++
si crees que mejora la legibilidad A veces, Bash da demasiadas formas de hacer las cosas, supongo que la filosofía Perl, cuando quizás Python "solo hay una forma correcta de hacerlo" podría ser más apropiado. ¡Esa es una declaración discutible si alguna vez hubo una! De todos modos, sugeriría que el objetivo (en este caso) no es simplemente incrementar una variable, sino (regla general) también escribir código que otra persona pueda entender y apoyar. La conformidad hace un largo camino para lograr eso.
HTH
COUNTER=1
while [ Your != "done" ]
do
echo " $COUNTER "
COUNTER=$[$COUNTER +1]
done
BASH PROBADO: Centos, SuSE, RH
count=0
base=1
(( count += base ))