Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

250
Vistas
¿Por qué Shell no establece una variable que se canaliza?

Tengo una variable que estoy tratando de establecer algo como esto:

 #!/bin/sh found=0 id=1 echo "Hello" | while [ $id != 5 ] do id=`expr $id + 1` echo $id found=1 done echo "found = $found" // I expect this to be 1

¿Por qué y cómo establecer este valor? Me veo obligado a usar así (entubado), porque el código real en el entorno de producción es:

 found=0 id=1 my_mount_name="/opt/insiteone/fuse-mount" echo "select file_system_id, mount_name from SystemTable" | mysql ifm -uroot -pinsite3 | while read file_system_id mount_name do if [ "$id" == "$file_system_id" -a "$my_mount_name" == "$mount_name" ]; then echo "Match found for file system ID and mount name" found=1 fi done echo "found = $found" // I expect this to be 1, when a match, but does not
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

La tubería corre en una subcapa. Puedes hacer algunas cosas para que funcione, la más simple es:

 found=0 id=1 my_mount_name="/opt/insiteone/fuse-mount" echo "select file_system_id, mount_name from SystemTable" | mysql ifm -uroot -pinsite3 | { while read file_system_id mount_name do if [ "$id" == "$file_system_id" -a "$my_mount_name" == "$mount_name" ]; then echo "Match found for file system ID and mount name" found=1 fi done echo "found = $found"; } # Note the enclosing {}. Inside the black, the variable $found is set. # After this comment, it will be zero.

Esta técnica puede requerir que el bloque envolvente sea bastante grande, por lo que es posible que desee refactorizar el resto del script para que sea utilizable. Otra opción es usar un fifo o colocar la canalización echo/mysql en una sustitución de proceso. (Este último no es portátil, pero funciona en bash, lo que puede ser adecuado). Sin embargo, en este caso particular, probablemente sea mejor hacer algo como:

 found=0 id=1 my_mount_name="/opt/insiteone/fuse-mount" echo "select file_system_id, mount_name from SystemTable" | mysql ifm -uroot -pinsite3 | { while read file_system_id mount_name do if [ "$id" == "$file_system_id" -a "$my_mount_name" == "$mount_name" ]; then echo "Match found for file system ID and mount name" exit 0 # Exit the subshell succesfully fi done exit 1; } && found=1
over 4 years ago · Santiago Trujillo Denunciar

0

Puede pasar las variables al entorno del subshell:

 foo=1 bar=2 echo "sds" | foo="$foo" bar="$bar" while ...
over 4 years ago · Santiago Trujillo Denunciar

0

Como comentó @fedorqui, bash coloca los componentes de la canalización en subcapas separadas, por lo que los cambios en sus variables desaparecen cuando la subcapa sale.

Hay 2 estrategias para lidiar con esto:

  1. solo use las variables modificadas en la misma subcapa

     echo "Hello" | { while [ $id != 5 ] do ((id++)) echo $id found=1 done echo "found = $found" // I expect this to be 1 }

    Esto puede ser un problema si tiene mucho código que se basa en esas variables

  2. reemplazar la tubería con sustitución de proceso. Esto significa que el ciclo while no se ejecuta en un subshell, se ejecuta en el shell actual:

     while [ $id != 5 ] do ((id++)) echo $id found=1 done < <(echo "Hello") echo "found = $found" // I expect this to be 1

    Esto puede tener problemas de legibilidad, pero puede poner tantos saltos de línea dentro de <(...) como desee.

    Su código de producción reescrito con sustitución de proceso (y sintaxis condicional bash/ksh):

     found=0 id=1 my_mount_name="/opt/insiteone/fuse-mount" while read file_system_id mount_name; do if [[ $id == $file_system_id ]] && [[ $my_mount_name == $mount_name ]]; then echo "Match found for file system ID and mount name" found=1 fi done < <( echo "select file_system_id, mount_name from SystemTable" | mysql ifm -uroot -pinsite3 ) echo "found = $found"
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda