テスト条件を含む Bash スクリプトの case ステートメントが動作しない

テスト条件を含む Bash スクリプトの 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何の関係もありません。詳細については、を参照してください。たとえば、関数を作成してその中で定義すると、他の (古い) 関数が干渉するリスクなしに、関数内で使用できるようになります。var2var2help localvalidate_invoice_numberlocal var2until [[ -n "${var2}" ]]; dovar2


次のコードは、 から の範囲から 2 つの乱数を取得しようとする試みですが、欠陥が0あります9999。Bash では、は$RANDOMから の範囲のランダムな整数に展開されます。Bashに対してランダムな数値を照会し続け、(偶然に)期待を満たす数値を取得します。これは、ユーザーに照会するアプローチに似ています。目的の範囲からランダムな整数を取得する最も速い方法ではありませんが、この場合も根本的な欠陥はありません。欠陥は、コードのように を再利用することにあります。stderr への診断メッセージは、何が起こっているかを理解するのに役立ちます。032767var2

#!/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

コードを実行すると、2 番目のループでは新しい乱数がまったく取得されないことがわかります。次に、次のコードを試してみましょう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(関数内でローカルでない限り) 1 つのスニペットから別のスニペットに残ります。これにより、問題がさらに強調されます。

関連情報