
У меня есть довольно длинный скрипт (основной скрипт). Я включу его сюда, так как считаю, что он может иметь отношение к ответу, поэтому, пожалуйста, не ненавидьте меня. Все в этом скрипте работает. Единственное, с чем я борюсь, это case *www1) и *www2) ближе к концу, которые по сути одинаковы. Тест NULL работает, и данные, которые вводятся в поля Zentiy, обрабатываются правильно для этих случаев. Однако, если я ничего не ввожу в соответствующие поля Zenity (invoice_number и note), else until [[ -n "${var2}" ]]; do...
они игнорируются. В конце скрипта я включил еще один более упрощенный скрипт только для рассматриваемого случая (упрощенный). Когда я запускаю его, проблем не возникает, и все работает так, как и ожидалось. Случай просто скопирован из оригинала, поэтому я рву на себе волосы, почему один работает, а другой нет. Кто-нибудь готов помочь с этим?
Основной сценарий:
#!/bin/bash
work_number="$(zenity --entry --text "ENTER number of work/job entries:" --entry-text "1")"
a=1
until
[[ $work_number -lt $a ]]
do
input="$(zenity --forms --title="table work" --text="Add a new job" --separator="," \
--add-entry="ENTER clientid: " \
--add-entry="ENTER job_start, -t time without time zone, e.g. '11:45:00', seconds allways zero: " \
--add-entry="ENTER job_finish, -t time without time zone, e.g. '11:45:00', seconds allways zero: " \
--add-entry="ENTER number_catchers, -t numeric, must be 0 if no waste has been collected or NULL if it has yet to be assigned to a tip run: " \
--add-entry="ENTER mower_front, -t numeric:" \
--add-entry="ENTER mower_back, -t numeric: " \
--add-entry="ENTER categoryid: " \
--add-entry="ENTER price, -t numeric: " \
--add-entry="ENTER invoice_number, -t text: " \
--add-entry="ENTER note, -t text: " \
--add-entry="ENTER a tip_runid, -t integer: ")"
psql -tA -U chh1 -d crewdb -c "SELECT SETVAL('work_workid_seq', (SELECT MAX(workid) FROM work), true);" >/dev/null 2>&1
dlink="$(psql -tA -U chh1 -d crewdb -c "SELECT MAX(date_linkid) FROM date_link;")"
startt="$(echo "$input" | awk -F, -v OFS=, '{print $2}')"
finisht="$(echo "$input" | awk -F, -v OFS=, '{print $3}')"
st="$( date --date="$startt" +%s 2>/dev/null )"
ft="$( date --date="$finisht" +%s 2>/dev/null )"
if [ -n "$st" -a "$ft" ] ; then
startt="$(date +%H:%M -d "$startt" )"
finisht="$(date +%H:%M -d "$finisht" )"
tzdiff="$(( ft - st ))"
else
tzdiff=0
fi
while [[ ( ( ! "$startt" =~ ^[0-1][0-9]:[0-5][0-9]$ ) && ( ! "$startt" =~ ^[0-2][0-3]:[0-5][0-9]$ ) ) ||
( ( ! "$finisht" =~ ^[0-1][0-9]:[0-5][0-9]$ ) && ( ! "$finisht" =~ ^[0-2][0-3]:[0-5][0-9]$ ) ) ||
( "$tzdiff" -le 0 ) ]];
do
var2="$(zenity --forms --title="job start time and/or job finish time are incorrect" --text "Add a job start time and finish_time" --separator="," \
--add-entry="WARNING! Something went wrong. Please enter a valid job start time, e.g. 8:20: " \
--add-entry="WARNING! Something went wrong. Please enter a valid job finish time, e.g. 12:30: ")"
tzdiff=0
if [ -n "$var2" ] ; then
b1=$(echo "$var2" | cut -d, -f1 )
b2=$(echo "$var2" | cut -d, -f2 )
if [ -n "$b1" -a -n "$b2" ] ; then
tz1=$( date --date="$b1" +%s 2>/dev/null )
tz2=$( date --date="$b2" +%s 2>/dev/null )
if [ -n "$tz1" -a -n "$tz2" ] ; then
startt=$(date +%H:%M -d "$b1" )
finisht=$(date +%H:%M -d "$b2" )
tzdiff=$(( tz2 - tz1 ))
fi
fi
fi
done
var2="$startt,$finisht"
input="$( echo "$input" | awk -v vard="$dlink" -v vart="$var2" 'BEGIN { FS="," } { print $1"xxx1" "," vard"ddd" "," vart "," $4"xxx2" "," $5"xxx3" "," $6"xxx4" "," $7"xxx5" "," $8"xxx6" "," $9"www1" "," $10"www2" "," $11"xxx7" ; }' )"
IFS=, read -ra array1 <<<"$input"
out=""
for i in "${array1[@]}"; do
case "$i" in
*ddd) out="$out,${i/%ddd/}";;
*xxx1) if [[ "${i/%xxx1/}" =~ ^[0-9]+$ ]]; then
out="$out,${i/%xxx1/}"
elif [[ "${i/%xxx1/}" = NULL ]]; then
out="$out,${i/%xxx1/}"
else until [[ ${var2} =~ ^[0-9]+$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="clientid field in table work" --text "Add a clientid" --separator="," \
--add-entry="WARNING! You either forgot to enter a clientid or didn't enter a number. Please enter a valid clientid: ")"
done
out="$out,${var2}"
fi
;;
*xxx2) if [[ "${i/%xxx2/}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
out="$out,${i/%xxx2/}"
elif [[ "${i/%xxx2/}" = NULL ]]; then
out="$out,${i/%xxx2/}"
else until [[ ${var2} =~ ^[0-9]+([.][0-9]+)?$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="number of catchers field in table work" --text "Add number of catchers" --separator="," \
--add-entry="WARNING! You either forgot to enter number of catchers or didn't enter a number. Please enter a valid number of catchers: ")"
done
out="$out,${var2}"
fi
;;
*xxx3) if [[ "${i/%xxx3/}" =~ ^[0-9]+$ ]]; then
out="$out,${i/%xxx3/}"
elif [[ "${i/%xxx3/}" = NULL ]]; then
out="$out,${i/%xxx3/}"
else until [[ ${var2} =~ ^[0-9]+$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="front mower wheel hight field in table work" --text "Add front mower wheel hight" --separator="," \
--add-entry="WARNING! You either forgot to enter a front mower wheel hight or didn't enter a number. Please enter a valid front mower wheel hight: ")"
done
out="$out,${var2}"
fi
;;
*xxx4) if [[ "${i/%xxx4/}" =~ ^[0-9]+$ ]]; then
out="$out,${i/%xxx4/}"
elif [[ "${i/%xxx4/}" = NULL ]]; then
out="$out,${i/%xxx4/}"
else until [[ ${var2} =~ ^[0-9]+$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="back mower wheel hight field in table work" --text "Add back mower wheel hight" --separator="," \
--add-entry="WARNING! You either forgot to enter a back mower wheel hight or didn't enter a number. Please enter a valid back mower wheel hight: ")"
done
out="$out,${var2}"
fi
;;
*xxx5) if [[ "${i/%xxx5/}" =~ ^[0-9]+$ ]]; then
out="$out,${i/%xxx5/}"
elif [[ "${i/%xxx5/}" = NULL ]]; then
out="$out,${i/%xxx5/}"
else until [[ ${var2} =~ ^[0-9]+$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="categoryid field in table work" --text "Add a categoryid" --separator="," \
--add-entry="WARNING! You either forgot to enter a categoryid or didn't enter a number. Please enter a valid categoryid: ")"
done
out="$out,${var2}"
fi
;;
*xxx6) if [[ "${i/%xxx6/}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
out="$out,${i/%xxx6/}"
elif [[ "${i/%xxx6/}" = NULL ]]; then
out="$out,${i/%xxx6/}"
else until [[ ${var2} =~ ^[0-9]+([.][0-9]+)?$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="price field in table work" --text "Add price" --separator="," \
--add-entry="WARNING! You either forgot to enter price or didn't enter a number. Please enter a valid price: ")"
done
out="$out,${var2}"
fi
;;
*xxx7) if [[ "${i/%xxx7/}" =~ ^[0-9]+$ ]]; then
out="$out,${i/%xxx7/}"
elif [[ "${i/%xxx7/}" = NULL ]]; then
out="$out,${i/%xxx7/}"
else until [[ ${var2} =~ ^[0-9]+$ ]] || [[ ${var2} = NULL ]]; do
var2="$(zenity --forms --title="tip_runid field in table work" --text "Add a tip_runid" --separator="," \
--add-entry="WARNING! You either forgot to enter a tip_runid or didn't enter a number. Please enter a valid tip_runid: ")"
done
out="$out,${var2}"
fi
;;
*ttt) out="$out,'${i/%ttt/}:00'";;
*www1) if [[ "${i/%www1/}" = NULL ]]; then
out="$out,${i/%www1/}"
elif [[ -n "${i/%www1/}" ]]; then
out="$out,\$\$${i/%www1/}\$\$"
else until [[ -n "${var2}" ]]; do
var2="$(zenity --forms --title="invoice number field in table work" --text "Add a invoice number" --separator="," \
--add-entry="WARNING! You either forgot to enter a invoice number. Please enter a invoice number or NULL: ")"
if [[ "${var2}" = NULL ]]; then
out="$out,${var2}"
else
out="$out,\$\$${var2}\$\$"
fi
done
fi
;;
*www2) if [[ "${i/%www2/}" = NULL ]]; then
out="$out,${i/%www2/}"
elif [[ -n "${i/%www2/}" ]]; then
out="$out,\$\$${i/%www2/}\$\$"
else
until [[ -n "${var2}" ]]; do
var2="$(zenityi --forms --title="note field in table work" --text "Add a note" --separator="," \
--add-entry="WARNING! You either forgot to enter a note. Please enter a note or NULL: ")"
if [[ "${var2}" = NULL ]]; then
out="$out,${var2}"
else
out="$out,\$\$${var2}\$\$"
fi
done
fi
;;
*) out="$out,'${i}:00'";;
esac;
done
echo "${out:1}"
let a++
done
Упрощенный сценарий:
#!/bin/bash
work_number="$(zenity --entry --text "ENTER number of work/job entries:" --entry-text "1")"
a=1
until
[[ $work_number -lt $a ]]
do
input="$(zenity --forms --title="table work" --text="Add a new job" --separator="," \
--add-entry="ENTER a: " \
--add-entry="ENTER invoice reference field: " \
--add-entry="ENTER b: ")"
input="$( echo "$input" | awk 'BEGIN { FS="," } { print $1 "," $2"www1" "," $3 ; }' )"
IFS=, read -ra myarray <<<"$input"
out=""
for i in "${myarray[@]}"; do
case "$i" in
*www1) if [[ "${i/%www1/}" = NULL ]]; then
out="$out,${i/%www1/}"
elif [[ -n "${i/%www1/}" ]]; then
out="$out,\$\$${i/%www1/}\$\$"
else until [[ -n "${var2}" ]]; do
var2="$(zenity --forms --title="invoice number field in table work" --text "Add a invoice number" --separator="," \
--add-entry="WARNING! You either forgot to enter a invoice number. Please enter a invoice number or NULL: ")"
if [[ "${var2}" = NULL ]]; then
out="${var2}"
else
out="\$\$${var2}\$\$"
fi
done
fi
;;
esac
done
out="${out#,}"
printf 'out=%s\n' "$out"
echo "$out"
let a++
done
решение1
Объяснение
Вы повторно используете var2
переменную, не отменив ее ( unset var2
) или не присвоив ей пустую строку ( var2=''
). Поэтому until [[ -n "${var2}" ]]; do …; done
использует некоторые старыенепустойзначение и код вместо него …
никогда не выполняется.
В упрощенном сценарии var2
все еще не установлено, когда вы впервые попадаете в until [[ -n "${var2}" ]]; do
. В этом разница.
Каждый раз, когда вы пишете, until [[ -n "${var2}" ]]; do
спрашивайте себя, должно ли иметь значение текущее значение переменной (из предыдущего цикла или около того). Если оно не должно иметь значения, то сделайте его неважным: отмените установку переменной непосредственно перед until
.
Альтернативой является организация вашего кода в функции. В функции в Bash вы можете определить локальные переменные. Локальная var2
переменная не будет иметь ничего общего с var2
(если вообще будет) в основном скрипте или с var2
другим вызовом этой или другой функции. help local
Подробности см. в разделе. Например, если вы создаете функцию validate_invoice_number
и определяете ее local var2
в ней, то вы сможете использовать ее until [[ -n "${var2}" ]]; do
в функции без риска, что какая-то другая (старая) var2
помешает.
Пример
Следующий фрагмент кода представляет собой ошибочную попытку получить два случайных числа из диапазона от 0
до 9999
. В Bash $RANDOM
расширяется до случайного целого числа из диапазона от 0
до 32767
Мы продолжим запрашивать у Bash случайные числа, пока (случайно) не получим то, которое соответствует нашим ожиданиям. Это похоже на ваш подход, когда вы запрашиваете пользователя. Это не самый быстрый метод получения случайного целого числа из желаемого диапазона, но в этом случае он также не является принципиально ошибочным. Ошибка заключается в повторном использовании var2
, как в вашем коде. Диагностические сообщения в stderr здесь, чтобы помочь вам понять, что происходит.
#!/bin/bash
for i in 1 2; do
echo "Loop $i starts. var2 is ${var2:-empty or unset}." >&2
until [ "$var2" -lt 10000 ] 2>/dev/null; do
echo "Trying new random number." >&2
var2="$RANDOM"
done
echo "Expectation met. Printing the result." >&2
echo "$var2"
echo "Loop $i ends. var2 is ${var2:-empty or unset}." >&2
done
Запустите код, и вы увидите, что второй цикл вообще не получает нового случайного числа. Теперь попробуем с unset
:
#!/bin/bash
for i in 1 2; do
echo "Loop $i starts. var2 is ${var2:-empty or unset}." >&2
unset var2
echo "Loop $i continues. var2 is ${var2:-empty or unset}." >&2
until [ "$var2" -lt 10000 ] 2>/dev/null; do
echo "Trying new random number." >&2
var2="$RANDOM"
done
echo "Expectation met. Printing the result." >&2
echo "$var2"
echo "Loop $i ends. var2 is ${var2:-empty or unset}." >&2
done
Другой подход заключается в использовании local var2
в функции:
#!/bin/bash
gimme_random () {
local var2
echo "Function starts. var2 inside is ${var2:-empty or unset}." >&2
until [ "$var2" -lt 10000 ] 2>/dev/null; do
echo "Trying new random number." >&2
var2="$RANDOM"
done
echo "Expectation met. Printing the result." >&2
echo "$var2"
echo "Function ends. var2 inside is ${var2:-empty or unset}." >&2
}
for i in 1 2; do
echo "Loop $i starts. var2 is ${var2:-empty or unset}." >&2
gimme_random
echo "Loop $i ends. var2 is ${var2:-empty or unset}." >&2
done
Это работает так, как и ожидалось. Переменная внутри функции не имеет связи с переменной вне функции. Когда функция запускается снова, переменная в новом экземпляре становится локальной для экземпляра.
Попробуйте без него, local var2
и он будет вести себя как первый (неправильный) фрагмент. В этом случае var2
снаружи и внутри функции (оба экземпляра) одно и то же var2
.
Также обратите внимание, если вы запускаете фрагменты, просто вставляя их последовательно в одну оболочку, то var2
(если только это не локально в функции) будут сохраняться от одного фрагмента к другому. Это еще больше подчеркнет проблему.