for 루프와 중첩된 if 문을 사용하여 독특한 결과를 제공하는 Bash 함수

for 루프와 중첩된 if 문을 사용하여 독특한 결과를 제공하는 Bash 함수

나는 나를 당황하게 만드는 다음 bash 기능을 가지고 있습니다. zenity 상자에 다음을 입력하면 ...

직원 ID = 2 카테고리 ID = 3

나는 다음을 얻습니다: 2 3

만약에...

직원 ID = 카테고리 ID = 3

두 번째 zenity 창이 열린 후 2를 입력하면 다음과 같은 결과가 나타납니다. 2 3

그런데 내가 들어갈 때

직원 ID = 2 카테고리 ID =

추가 Zenity 창이 열리지 않고 다음과 같은 메시지가 표시됩니다. 2

내가 정말로 끝내고 싶은 것은 테스트가 실행된 후 2,3입니다.

여기에 무엇이 잘못되었는지 아는 사람이 있나요?

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

답변1

여기서 무슨 문제가 있나요?

작동 방식에 대한 가정은 실제 작동 read방식과 다릅니다 . readBash에서 다음 코드를 실행하세요.

how_many () { IFS=, read -ra array1 <<<"$1"; echo "${#array1[@]}"; }
how_many "2,3"
how_many ",3"
how_many "2,"

당신은 얻을 것이다 2, 2, 1. 마지막 숫자가 눈에 띕니다. 이는 후행 구분 기호( ,이 경우) read가 종결자처럼 처리된다는 것을 의미합니다. 빈 필드가 배열로 읽히지 않고 배열이 너무 짧은 요소로 끝나게 됩니다. 코드에서 이런 일이 발생하면 for i in "${array1[@]}"첫 번째 필드에 대해서만 루프가 실행됩니다.

해결책은 다음을 도입하는 것일 수 있습니다.추가의 ,의도적으로 후행 터미네이터로 사용되었습니다. 그런 다음 read세 번째 필드는 읽지 않지만 항상 두 개의 필드를 읽습니다(두 번째 필드가 비어 있는 경우에도). 추가 항목을 추가할 때 차이점을 확인하세요 ,.

how_many () { IFS=, read -ra array1 <<<"$1,"; echo "${#array1[@]}"; }
how_many "2,3"
how_many ",3"
how_many "2,"
how_many ","

출력은 2매번입니다.

<<<"$emp,"이 방법 으로 코드를 수정하려면 <<<"$emp".


else코드를 수정하면 블록이 두 번 이상 실행될 때(즉, 두 필드가 처음에 유효하지 않은 경우) 오작동합니다 . 왜냐하면 당신은var2변수 재사용다시.

나는 당신이 이것을 피하곤 했다고 생각 local var2하지만 블록이나 루프의 단일 반복이 local아닌 함수에서 변수를 로컬로 만듭니다 . 동일한 함수 인스턴스에서 재사용하고 있습니다 .elseforvar2num

함수를 한 번 호출합니다. 내부는 var2항상 동일하며 var2, 이 함수 호출을 통해 외부 local와 구별될 뿐입니다 . 함수 외부에서 var2사용했다면 함수 안의 함수는 구별됩니다. 두 번 이상 var2호출하면 num각 호출마다 고유한 var2. 둘 다 발생하지 않습니다. 함수를 한 번 호출하고 변수를 재사용합니다.거기. 두 필드가 유효하지 않은 경우 변수는 첫 번째 필드에 사용된 다음재사용두 번째 필드의 경우.

그러나 코드를 다시 작성하여 validate루프 내에서 일부 함수(예: )가 호출되는 경우:

for i in "${array1[@]}"; do validate "$i"; …

함수 local var2에서 사용하면 각 함수 호출에서 구별됩니다. 이것이 도움이 될 수 있는 방법입니다. 각 루프에서 새로 호출되고 해당 지역 변수는 동일한 이름을 가진 다른 변수에 연결되지 않고 새로 초기화됩니다. 그러나 여전히 지역 변수를 재사용할 수 있습니다.validatevar2localvalidate내부에무언가를 중단시키는 방식으로 함수를 사용합니다(현재 함수 var2에서 재사용하는 방법과 유사 num).

위의 내용을 작성한 후이미 연결된 답변.


Note는 p=$(stuff); echo "$p"와 거의 동일하며 echo "$(stuff)", 거의 항상 just 여야 합니다 stuff. 읽어주세요이 답변자세히 설명되어 있는 곳입니다 var=$(stuff); echo "$var".

관련 정보