Tengo el siguiente script simple donde estoy ejecutando un bucle y quiero mantener a COUNTER
. No puedo entender por qué el contador no se está actualizando. ¿Se debe a la subshell que se está creando? ¿Cómo puedo solucionar esto potencialmente?
#!/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
Respuestas:
Primero, no estás aumentando el contador. Cambiando
COUNTER=$((COUNTER))
enCOUNTER=$((COUNTER + 1))
oCOUNTER=$[COUNTER + 1]
aumentará ella.En segundo lugar, es más difícil propagar hacia atrás las variables del subshell a la persona que llama a medida que usted supone. Las variables en una subshell no están disponibles fuera de la subshell. Estas son variables locales al proceso hijo.
Una forma de resolverlo es usar un archivo temporal para almacenar el valor intermedio:
fuente
$[...]
está en desuso? ¿Hay una solución alternativa?$[...]
fue utilizado porbash
antes$((...))
fue adoptado por el shell POSIX. No estoy seguro de que alguna vez se haya desaprobado formalmente, pero no puedo encontrar ninguna mención al respecto en labash
página de manual, y parece que solo es compatible con la compatibilidad con versiones anteriores....
BASH PROBADO: Centos, SuSE, RH
fuente
$[ ]
sintaxis está en desuso. stackoverflow.com/questions/10515964/…Es una construcción bastante torpe en la programación moderna.
se ve más "moderno". También puedes usar
si crees que eso mejora la legibilidad. A veces, Bash ofrece demasiadas formas de hacer las cosas, supongo que la filosofía de Perl, 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) también escribir código que alguien más pueda entender y apoyar. La conformidad hace mucho para lograrlo.
HTH
fuente
Tratar de usar
en vez de
fuente
let "COUNTER++"
(( COUNTER++ ))
(sin signo de dólar)(( COUNTER++ ))
pero cuando lo cambiéCOUNTER=$((COUNTER + 1))
funcionó.GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Creo que esta única llamada awk es equivalente a tu
grep|grep|awk|awk
canalización: pruébelo. Su último comando awk parece no cambiar nada en absoluto.El problema con COUNTER es que el ciclo while se ejecuta en una subshell, por lo que cualquier cambio en la variable desaparecerá cuando la subshell salga. Debe acceder al valor de COUNTER en esa misma subshell. O tome el consejo de @ DennisWilliamson, use una sustitución de proceso y evite la subshell por completo.
fuente
fuente
En lugar de utilizar un archivo temporal, puede evitar crear una subshell alrededor del
while
bucle mediante la sustitución del proceso.Por cierto, deberías poder transformar todo eso
grep, grep, awk, awk, awk
en un soloawk
.Comenzando con Bash 4.2, hay una
lastpipe
opción quefuente
lastpipe
. Por cierto, probablemente deberías usar"${PIPESTATUS[@]}"
(en lugar de asterisco).minimalista
fuente
Esto es todo lo que necesitas hacer:
Aquí hay un extracto de Learning the bash Shell , 3rd Edition, pp. 147, 148:
..........................
Ver http://www.safaribooksonline.com/a/learning-the-bash/7572399/
fuente
if
declaración:if [[ $((needsComma++)) -gt 0 ]]; then printf ',\n'; fi
correcta o incorrecta, esta es la única versión que funcionó de manera confiable.i=1; while true; do echo $((i++)); sleep .1; done
if (( needsComma++ > 0 )); then
oif (( needsComma++ )); then
Este es un ejemplo simple
fuente
Parece que no actualizaste
counter
el script, usacounter++
fuente
Hubo dos condiciones que hicieron que la expresión
((var++))
fallara para mí:Si configuro bash en modo estricto (
set -euo pipefail
) y si comienzo mi incremento en cero (0).Comenzar en uno (1) está bien, pero cero hace que el incremento devuelva "1" al evaluar "++", que es un error de código de retorno distinto de cero en modo estricto.
Puedo usar
((var+=1))
ovar=$((var+1))
escapar de este comportamientofuente
El script de origen tiene algún problema con subshell. Primer ejemplo, probablemente no necesite subshell. Pero no sabemos qué se esconde bajo "Algo más de acción". La respuesta más popular tiene un error oculto, que aumentará la E / S y no funcionará con subshell, porque restaura el interior del bucle.
No agregue el signo '\', informará al intérprete bash sobre la continuación de la línea. Espero que te ayude a ti o a cualquiera. Pero en mi opinión, esta secuencia de comandos debe convertirse completamente a la secuencia de comandos AWK, o reescribirse a Python usando regexp, o perl, pero la popularidad de perl a lo largo de los años se degrada. Mejor hacerlo con python.
Versión corregida sin subshell:
Versión con subshell si es realmente necesario
fuente