Contador incremento en el bucle Bash no funciona
Tengo el siguiente script simple donde estoy ejecutando un bucle y quiero mantener un COUNTER
. No puedo entender por qué el contador no se está actualizando. ¿Se debe a la subcapa que se está creando? ¿Cómo puedo potencialmente arreglar 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
10 answers
Primero, no estás aumentando el contador. Cambiando COUNTER=$((COUNTER))
en COUNTER=$((COUNTER + 1))
o COUNTER=$[COUNTER + 1]
lo aumentará.
En segundo lugar, es más complicado propagar las variables de subconjunto al destinatario a medida que conjeturas. Las variables de una subcapa no están disponibles fuera de la subcapa. Estas son variables locales al proceso hijo.
Una forma de resolverlo es usando 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 12:30:31
COUNTER=1
while [ Your != "done" ]
do
echo " $COUNTER "
COUNTER=$[$COUNTER +1]
done
TESTED BASH: Centos, SuSE, RH
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 19:19:48
COUNTER=$((COUNTER+1))
Es una construcción bastante torpe en la programación moderna.
(( COUNTER++ ))
Parece más "moderno". También puede utilizar
let COUNTER++
Si crees que eso mejora la legibilidad. A veces, Bash da demasiadas maneras de hacer las cosas - filosofía Perl supongo - cuando quizás la Python "solo hay una manera correcta de hacerlo" podría ser más apropiada. ¡Esa es una declaración discutible si alguna vez hubo una! De todos modos, sugeriría que el objetivo (en este caso) no es solo incrementar una variable, sino (regla general) para escribir también código que alguien más pueda entender y apoyar. La conformidad va un largo camino para lograrlo.
HTH
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-06 09:41:20
count=0
base=1
(( count += base ))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-16 00:29:17
Intenta usar
COUNTER=$((COUNTER+1))
En lugar de
COUNTER=$((COUNTER))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 12:23:37
Creo que esta única llamada awk es equivalente a su canalización grep|grep|awk|awk
: por favor, pruébela. Su último comando awk parece no cambiar nada en absoluto.
El problema con COUNTER es que el bucle while se está ejecutando en una subcapa, por lo que cualquier cambio en la variable desaparece cuando la subcapa sale. Es necesario acceder al valor de CONTADOR en ese mismo subshell. O tome el consejo de @DennisWilliamson, use una sustitución de proceso y evite la subcapa por completo.
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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 14:17:02
En lugar de usar un archivo temporal, puede evitar crear una subcapa alrededor del bucle while
mediante la sustitución de procesos.
while ...
do
...
done < <(grep ...)
Por cierto, deberías ser capaz de transformar todo eso grep, grep, awk, awk, awk
en un solo awk
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 13:59:04
Minimalista
counter=0
((counter++))
echo $counter
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-05 04:59:46
Esto es todo lo que necesitas hacer:
$((COUNTER++))
Aquí hay un extracto de Aprendiendo la cáscara de bash , 3a Edición, pp. 147, 148:
bash las expresiones aritméticas son equivalentes a sus contrapartes en los lenguajes Java y C.[9] Precedencia y asociatividad son lo mismo como en C. La tabla 6-2 muestra los operadores aritméticos que son compatibles. Aunque algunos de estos son (o contienen) caracteres especiales, hay no hay necesidad de barra invertida-escapar de ellos, porque están dentro del $((...)) sintaxis.
..........................
Los operadores ++ y - son útiles cuando se desea incrementar o decrementar un valor por uno.[11] Funcionan igual que en Java y C, por ejemplo, value++ incrementa el valor en 1. Esto se llama post-incremento; también hay un pre-incremento : ++valor . La diferencia se hace evidente con un ejemplo:
$ i=0
$ echo $i
0
$ echo $((i++))
0
$ echo $i
1
$ echo $((++i))
2
$ echo $i
2
Véase http://www.safaribooksonline.com/a/learning-the-bash/7572399 /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-18 18:58:07
Parece que no actualizaste el counter
es el script, usa counter++
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 12:26:40