Quiero que se le solicite al usuario una pregunta y luego proporcione la respuesta, que se almacenará en una variable llamada i, luego si la respuesta (que es un archivo) existe y se puede escribir, lo lee y greps cosas dentro del archivo y escribe esas cosas en uno nuevo. Si el archivo no existe o el usuario no tiene suficientes permisos sobre ese archivo, se muestra una advertencia, el programa permanece inactivo durante 3 segundos y los ciclos comienzan de nuevo. ¿Por qué no funciona? La advertencia simplemente no desaparecerá, ni el ciclo continuará.
echo "$(tput setaf 4) Tell me where the file is:" printf "\n" a=false while [ $a=true ]; do read i if [ -w $i ] then cat $i | grep stuff > i2 else a=true printf "Oh something is wrong, try again!" sleep 3 fi done
Respuesta
Tiene errores de sintaxis y lógicos.
El $a=true
es solo una cadena, NO una operación de comparación. Separe con espacios para que se lleve a cabo la comparación: "$a" = true
.
Con eso funcionando, el bucle no se ingresará en absoluto, ya que establece a=false
por adelantado.
DEBE finalmente entrar en el bucle, no podrá salir, ya que a
nunca configurado en cualquier cosa menos true
, ni se proporciona otro mecanismo de salida (por ejemplo, break
).
Respuesta
Como otros han señalado, tiene errores lógicos y errores de sintaxis en su código. El sitio ShellCheck es bueno para eliminar los errores de sintaxis.
Aquí está mi opinión sobre esto. Tengo dos versiones del código . El primero (que prefiero) no tiene interacción con el usuario, pero toma un nombre de ruta en la línea de comando. El segundo solicita interactivamente un nombre de ruta.
La razón por la que el primero no solicita interactivamente pathname es que hay poca diferencia si el usuario del script escribe el nombre de la ruta en la línea de comando o en la línea de comandos de su script, y tener la solicitud de script para el nombre de la ruta lo descalifica para ser utilizado por ejemplo. un trabajo cron o en cualquier otro lugar donde no haya una terminal adjunta.
#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi
El echo
de arriba será ejecutado cuando
- el archivo en
$pathname
no se puede «leer, o - el archivo
i2
no se puede escribir, o - el patrón no se encontró en
$pathname
(esto es diferente de su código, pero vea a continuación) .
El mensaje de error se escribe como error estándar, como es la costumbre con los mensajes de diagnóstico en general.
Con avisos interactivos y retraso:
#!/bin/bash while true; do read -r -p "Pathname: " pathname if grep "pattern" <$pathname >i2; then break fi echo "Something is wrong" >&2 sleep 3 done
Aquí, tenemos un bucle infinito que lee del usuario y sale del bucle si la llamada grep
salió bien. Si grep
falló por cualquier motivo (uno de los tres motivos anteriores), se volverá a solicitar el nombre de la ruta.
Ambos fragmentos de código con un prueba para un archivo legible (el grep
puede fallar al no encontrar nada o al no poder escribir en su archivo de salida.
Primero el no interactivo versión:
#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2
Luego, la versión interactiva:
#!/bin/bash while true; do read -r -p "Pathname: " pathname if [ -r "$pathname" ]; then grep "pattern" <$pathname >i2 break fi echo "Something is wrong" >&2 sleep 3 done
O una versión interactiva donde el ciclo solo se ocupa de la entrada y la validación del usuario:
#!/bin/bash while true; do read -r -p "Pathname: " pathname [ -r "$pathname" ] && break echo "Something is wrong" >&2 sleep 3 done grep "pattern" <$pathname >i2
Respuesta
Intente usar simplemente romper para detener un bucle infinito como este:
echo "$(tput setaf 4) Tell me where the file is:" echo # This prints empty line like printf "\n" while true; do # "while true" or "while :" is infinite loop read i if [ -r $i ] # You probably mean -r (readable) and not -w (writable) then cat $i | grep stuff > i2 break # "break" ends loop else echo -n "Oh something is wrong, try again!" # "echo -n" means print without newline character sleep 3 fi done
Los lugares modificados tienen comentarios con descripción.
grep <$i >i2
en lugar decat
. Además, cite las expansiones de variables cuando sea necesario, como en la prueba .