while-loop - statement - while do linux bash
salida de tuberÃa del proceso a sh while loop? (3)
Estoy intentando recorrer la salida de un proceso Perl, línea por línea, dentro de un ciclo while. Sin embargo, estoy teniendo dificultades con la sintaxis.
Intenté esto, pero obtuve un error de "redirección ambigua":
#!/bin/sh
while read line; do
echo "$line"
# do stuff with $line
done < $(perl process.pl)
./script.sh : line 6: $(perl process.pl): ambiguous redirect
Por ejemplo, una solución (ineficiente) sería:
#!/bin/sh
tmpFile=/tmp/tmpFile.txt
perl process.pl > $tmpFile
while read line; do
echo "$line"
# do stuff with $line
done < $tmpFile
Sé que puedo canalizar el proceso Perl a un ciclo while como:
perl process.pl | while ...
pero el ciclo while se ejecuta en una subshell, y necesito que algunas variables establecidas en el ciclo while permanezcan después de que termine el ciclo, por lo que esta no es una opción.
¿Que puedo hacer?
Use un documento aquí :
while IFS= read -r line; do
echo "$line"
# do stuff with $line
done <<EOF
$(perl process.pl)
EOF
Use un tubo con nombre; bash
sustitución del proceso de bash
es esencialmente azúcar sintáctico alrededor de esto.
mkfifo output
perl process.pl > output &
while IFS= read -r line; do
echo "$line"
# do stuff with $line
done < output
rm output
La tubería con nombre no requiere que process.pl
complete antes de que el ciclo while comience a consumir la salida.
Ya casi estás ahí. Prueba esto:
while read -r line; do
echo "$line"
# do stuff with $line
done < <(perl process.pl)
La única diferencia es <
lugar de $
.
$(cmd)
es una sustitución de comando, que se expande a la salida del comando entre paréntesis. Por otro lado, <(cmd)
es una sustitución de proceso . Tenga en cuenta que esta es una extensión de Bash, por lo que también debe cambiar su shebang para que sea #!/bin/bash
si desea utilizar este método.
Alternativamente, si no está utilizando Bash, simplemente puede usar una tubería en su lugar:
perl process.pl | while read -r line; do
echo "$line"
# do stuff with $line
done
Como un lado, casi siempre quiere usar el interruptor -r
con lectura