Tengo la siguiente función bash que me tiene despilfarrado. Si ingreso lo siguiente en las casillas de zenity...
ID de empleado = 2 ID de categoría = 3
Me sale lo siguiente: 2 3
si...
ID de empleado = ID de categoría = 3
Después de que se abre una segunda ventana de zenity, ingreso 2 y obtengo lo siguiente: 2 3
Sin embargo cuando entro
ID de empleado = 2 ID de categoría =
No se abre ninguna ventana adicional de Zenity y aparece lo siguiente: 2
Lo que realmente quiero obtener es 2,3 después de que se hayan realizado las pruebas.
¿Alguien sabe qué está mal aquí?
#!/bin/bash
num(){
emp=$(echo "$1" | awk -F, -v OFS=, '{print $1 "," $2}')
IFS=, read -ra array1 <<<"$emp"
p=$(for i in "${array1[@]}"
do
if [[ "${i}" =~ ^[0-9]+$ ]]; then
out="${i}"
elif
[[ "${i}" = NULL ]]; then
out="${i}"
else local var2
until [[ ${var2} =~ ^[0-9]+$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="table salaries_wages" --text "Add a number" --separator="," \
--add-entry="WARNING! You either forgot to enter or didn't enter a number. Please enter a valid number: ")"
done
out="${var2}"
fi
echo "$out"
done)
echo "$p"
}
input="$(zenity --forms --title="table salaries_wages" --text="Add a new salaries_wages entry" --separator="," \
--add-entry="ENTER employeeid: " \
--add-entry="ENTER categoryid: ")"
num "$input"
Respuesta1
¿Que esta mal aquí?
Su suposición de cómo read
funciona es diferente de cómo read
funciona realmente. Ejecute este código en Bash:
how_many () { IFS=, read -ra array1 <<<"$1"; echo "${#array1[@]}"; }
how_many "2,3"
how_many ",3"
how_many "2,"
Conseguirás 2
, 2
, 1
. Destaca el último número. Significa que el separador final ( ,
en este caso) se trata read
más como un terminador: el campo vacío después de él no se lee en la matriz y la matriz termina siendo un elemento demasiado corto. Si esto sucede en su código, for i in "${array1[@]}"
se ejecutará el bucle solo para el primer campo.
La solución puede ser introducir unextra ,
como terminador final a propósito. Entonces read
nunca leerá el tercer campo, pero siempre leerá dos campos (incluso si el segundo está vacío). Vea la diferencia cuando agrego un extra ,
:
how_many () { IFS=, read -ra array1 <<<"$1,"; echo "${#array1[@]}"; }
how_many "2,3"
how_many ",3"
how_many "2,"
how_many ","
La salida es 2
cada vez.
Para arreglar su código de esta manera use <<<"$emp,"
en lugar de <<<"$emp"
.
Si corrige el código, se comportará mal cuando el else
bloque se ejecute más de una vez (es decir, cuando ambos campos no sean válidos inicialmente); porque eresreutilizando la var2
variablede nuevo.
Supongo que solías local var2
evitar esto, pero local
haces que la variable sea local en una función, no en un else
bloque o en una única iteración de un for
bucle. Estás reutilizando var2
en la misma instancia de la num
función.
Estás llamando a la función una vez. En su interior var2
es siempre el mismo var2
, local
sólo lo distingue de cualquier var2
exterior esta misma invocación de la función. Si lo usara var2
fuera de la función, el de la función sería distinto. Si invocaste num
más de una vez, cada invocación usaría su propio archivo var2
. Ninguna de estas cosas sucede. Estás llamando a la función una vez y reutilizando la variable.allá. Cuando dos campos no son válidos, la variable se utiliza para el primer campo y luegoreutilizadopara el segundo campo.
Pero si reconstruye su código de modo que validate
se llame a alguna función (por ejemplo, ) desde dentro del bucle:
for i in "${array1[@]}"; do validate "$i"; …
y uso local var2
en la validate
función, entonces var2
en cada invocación de la función será distinta. Así es como local
puedo ayudar. En cada bucle validate
se llamará de nuevo, sus variables locales se inicializarán de nuevo sin ninguna conexión con otras variables con el mismo nombre. Sin embargo, aún podrá reutilizar una variable local.adentrola función de una manera que rompa algo (de manera similar a cómo estás reutilizando actualmente var2
en la num
función).
Después de escribir lo anterior, agregué un ejemplo alrespuesta ya vinculada.
Note p=$(stuff); echo "$p"
es casi equivalente a echo "$(stuff)"
, que casi siempre debería ser justo stuff
. Por favor leeesta respuestadonde profundiza var=$(stuff); echo "$var"
.