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
Author: MERose, 2012-05-09

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
 139
Author: bos,
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

 73
Author: Jay Stan,
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

 33
Author: Bill Parker,
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 ))
 14
Author: pkm,
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))
 12
Author: dbf,
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
}
 10
Author: glenn jackman,
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.

 7
Author: Dennis Williamson,
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
 6
Author: geekzspot,
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 /

 3
Author: C.E. Montijo,
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++

 0
Author: Yijie Shen,
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