
다소 긴 스크립트(메인 스크립트)가 있습니다. 답변과 관련이 있을 수 있다고 생각하므로 여기에 모든 내용을 포함하겠습니다. 그러니 저를 미워하지 마세요. 이 스크립트의 모든 내용은 작동합니다. 내가 겪고 있는 유일한 문제는 본질적으로 동일한 끝 부분의 *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
다음 범위의 임의의 정수로 확장됩니다 . (우연히) 기대에 맞는 숫자를 얻을 때까지 Bash에서 임의의 숫자를 계속 쿼리할 것입니다 0
. 32767
이는 사용자에게 쿼리하는 접근 방식과 유사합니다. 원하는 범위에서 임의의 정수를 얻는 가장 빠른 방법은 아니지만 이 경우에도 근본적으로 결함이 있는 것은 아닙니다. 결함은 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
(함수에서 로컬이 아닌 한) 한 코드 조각에서 다른 코드 조각으로 유지됩니다. 이것은 심지어 문제를 강조할 것입니다.