Ich habe die folgende Bash-Funktion, die mich in Verlegenheit bringt. Wenn ich Folgendes in die Zenity-Felder eingebe ...
Mitarbeiter-ID = 2 Kategorie-ID = 3
Ich erhalte folgendes: 2 3
Wenn...
Mitarbeiter-ID = Kategorie-ID = 3
Nachdem sich ein zweites Zenity-Fenster öffnet, gebe ich 2 ein und erhalte Folgendes: 2 3
Wenn ich jedoch
Mitarbeiter-ID = 2 Kategorie-ID =
Es öffnet sich kein weiteres Zenity-Fenster und ich erhalte folgende Meldung: 2
Am Ende möchte ich nach Abschluss der Tests ein Ergebnis von 2,3 erzielen.
Weiß jemand, was hier nicht stimmt?
#!/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"
Antwort1
was ist hier falsch?
Ihre Annahme, wie read
es funktioniert, weicht von der read
tatsächlichen Funktionsweise ab. Führen Sie diesen Code in Bash aus:
how_many () { IFS=, read -ra array1 <<<"$1"; echo "${#array1[@]}"; }
how_many "2,3"
how_many ",3"
how_many "2,"
Sie erhalten 2
, 2
, 1
. Die letzte Zahl fällt auf. Das bedeutet, dass das nachfolgende Trennzeichen ( ,
in diesem Fall) read
eher wie ein Abschlusszeichen behandelt wird: Das leere Feld danach wird nicht in das Array eingelesen und das Array ist am Ende ein Element zu kurz. Wenn dies in Ihrem Code passiert, for i in "${array1[@]}"
wird die Schleife nur für das erste Feld ausgeführt.
Die Lösung könnte darin bestehen, eineextra ,
als Abschlusszeichen mit Absicht. Dann read
wird nie das dritte Feld gelesen, aber immer zwei Felder (selbst wenn das zweite leer ist). Sehen Sie den Unterschied, wenn ich ein zusätzliches hinzufüge ,
:
how_many () { IFS=, read -ra array1 <<<"$1,"; echo "${#array1[@]}"; }
how_many "2,3"
how_many ",3"
how_many "2,"
how_many ","
Die Ausgabe erfolgt 2
jedes Mal.
Um Ihren Code auf diese Weise zu korrigieren, verwenden Sie <<<"$emp,"
anstelle von <<<"$emp"
.
Wenn Sie den Code reparieren, wird er sich falsch verhalten, wenn der else
Block mehr als einmal ausgeführt wird (d. h. wenn beide Felder anfänglich ungültig sind); denn SieWiederverwendung der var2
Variablewieder.
Ich vermute, Sie haben local var2
dies früher vermieden, aber local
die Variable lokal in einer Funktion erstellt, nicht in einem else
Block oder in einer einzelnen Iteration einer for
Schleife. Sie verwenden sie var2
in derselben Instanz der num
Funktion erneut.
Sie rufen die Funktion einmal auf. Darin var2
ist immer dasselbe var2
, local
nur unterscheidet sich var2
dieses Aufrufen der Funktion von allen außerhalb. Wenn Sie var2
außerhalb der Funktion verwenden würden, wäre das in der Funktion different . Wenn Sie num
mehr als einmal aufrufen würden, würde jeder Aufruf sein eigenes distinct verwenden var2
. Keines von beidem passiert. Sie rufen die Funktion einmal auf und verwenden die Variable erneutDort. Wenn zwei Felder ungültig sind, wird die Variable für das erste Feld verwendet und dannwiederverwendetfür das zweite Feld.
Wenn Sie Ihren Code jedoch so umbauen, dass eine Funktion (z. B. validate
) innerhalb der Schleife aufgerufen wird:
for i in "${array1[@]}"; do validate "$i"; …
local var2
und in der validate
Funktion verwenden , dann var2
wird jeder Aufruf der Funktion unterschiedlich sein. So local
kann es helfen. In jeder Schleife validate
wird sie neu aufgerufen, ihre lokalen Variablen werden neu initialisiert, ohne Verbindung zu anderen Variablen mit demselben Namen. Sie können jedoch weiterhin eine lokale Variable wiederverwendeninnendie Funktion auf eine Weise, die etwas kaputt macht (ähnlich der Art und Weise, wie Sie es derzeit var2
in der num
Funktion wiederverwenden).
Nachdem ich das Obige geschrieben hatte, fügte ich ein Beispiel hinzubereits verlinkte Antwort.
Hinweis p=$(stuff); echo "$p"
ist fast gleichbedeutend mit echo "$(stuff)"
, was fast immer nur sein sollte stuff
. Bitte lesen Siediese Antwortwo näher darauf eingegangen wird var=$(stuff); echo "$var"
.