내 스크립트가 여러 함수를 호출하는 이유는 무엇입니까? [복사]

내 스크립트가 여러 함수를 호출하는 이유는 무엇입니까? [복사]

나는 Linux를 매우 쉽게 설정할 수 있도록 몇 가지 스크립트 세트를 작성했습니다. 그래서 저는 이 스크립트를 별도의 함수로 만들어 모두 하나의 스크립트에 넣었습니다. 사용자가 숫자 중 하나를 입력하면 함수가 호출되도록 숫자를 설정했습니다. 그러나 사용자가 숫자를 입력하면 스크립트는 모든 함수를 호출합니다.

n=1
#note you need spaces between [ ]
while [ $n == 1 ]
do
    echo "Base install=1"
    echo "Mintrepos=2"
    echo "Asusn13 driver=3"
    echo "Install Standard openbox=4"
    echo "Install Xfceopenbox=5"
    echo "backing up standard open box config=6"
    echo "backing up openboxfce=7"
    echo
    read choice
    if [ "$choice"==1 ]
    then
        baseinstall
    fi
    if [ "$choice"==2 ]
    then
        linuxmintrepos
    fi
    if [ "$choice"==3 ]
    then
        asusn13driver
    fi
    if [ "$choice"==4 ]
    then
        standardopenbox
    fi
    if [ "$choice"==5 ]
    then
        xfceopenbox
    fi
    if [ "$choice"==6 ]
    then
        backupstandopenbox
    fi
    if [ "$choice"==7 ]
    then
        backupxfc4openbox
    fi
    echo "You installed: "
    if [ "$choice"==1 ]
    then
        echo "baseinstall"
    fi
    if [ "$choice"==2 ]
    then
        echo "linuxmintrepos"
    fi
    if [ "$choice"==3 ]
    then
        echo asusn13driver
    fi
    if [ "$choice"==4 ]
    then
        echo "standardopenbox"
    fi
    if [ "$choice"==5 ]
    then
        echo "xfceopenbox"
    fi
    if [ "$choice"==6 ]
    then
        echo "backupstandopenbox"
    fi
    if [ "$choice"==7 ]
    then
        echo "backupxfc4openbox"
        echo "If you would like to keep going, type in 1, if not, type in any other number"
    read n
    fi

done

답변1

바꾸다:

if [ "$choice"==1 ]

그리고:

if [ "$choice" = 1 ]

모든 후속 테스트에 대해 동일한 작업을 수행합니다.

설명하다

쉘이 이를 볼 때 "$choice"==1문자열을 봅니다. 예를 들어, choice2이면 문자열이 표시됩니다 2==1. 이것은 평등 테스트가 아닙니다. 문자열입니다. 비어 있지 않은 문자열이므로 테스트는 true를 반환합니다. 따라서 모든 선택이 실행됩니다.

동등성 테스트를 인식하려면 공백이 필요합니다.

또한 작은 점으로 [스타일 테스트의 경우 등호는 입니다 =. bash는 이를 허용 ==하지만 올바르지 않으며 다른 쉘에서는 작동하지 않습니다.

[...]명령줄에서 테스트 살펴보기

[명령줄에서 테스트가 작동하는 방식을 쉽게 탐색할 수 있습니다. 먼저, 빈 문자열이 false로 테스트된다는 것을 보여드리겠습니다.

$ if [ "" ]; then echo True; else echo False; fi
False

비어 있지 않은 문자열은 무엇이든 참입니다:

$ if [ abc ]; then echo True; else echo False; fi
True

이제 살펴보겠습니다 2==1.

$ if [ 2==1 ]; then echo True; else echo False; fi
True

2==1비어 있지 않은 문자열이므로 테스트는 true입니다 .

이제 공백을 추가하고 동등성을 테스트해 보겠습니다.

$ if [ 2 = 1 ]; then echo True; else echo False; fi
False
$ if [ 2 = 2 ]; then echo True; else echo False; fi
True

좀 더 미묘하게 말하자면, =여기서는 문자열 동일성 테스트가 제대로 작동합니다. 수치 동등성을 테스트하려면 대신 를 사용하십시오 -eq.

$ if [ 2 -eq 2 ]; then echo True; else echo False; fi
True

답변2

다른 사람들이 언급했듯이 귀하의 if test ...;fi진술은 문법적으로 정확하지 않지만 전체 접근 방식이 약간 조잡하다는 점은 주목할 가치가 있습니다. 이 스크립트 흐름에는 크게 개선할 수 있는 여러 측면이 있습니다. 특히 나중에 읽고 편집하기가 더 쉬울 것입니다.

첫째, 루프 set에서 반복적으로 선택할 수 있습니다 for. 그래서 가능한선택하다해당 선택자는 사용자에게 알리고 자동으로 생성되지만 스크립트에서는 이를 모두 문자열 목록에 넣을 수 있으므로 걱정할 필요가 없습니다.

set --
for c in \
    "Base install:base_fn"                             \
    "Mintrepos:mint_fn"                                \
    "Asusn13 driver:asus_fn"                           \
    "Install Standard openbox:std_obox_fn"             \
    "Install Xfceopenbox:xfce_obox_fn"                 \
    "backing up standard open box config:bkup_fn obox" \
    "backing up openboxfce:bkup_fn xfce"              
do
    set -- "$@" "${c##*:}"
    printf "'%s' = $#\n" "${c%:*}"
done

이는 호출을 fn_name위치 인수 배열로 인코딩하는 동시에 사용자에게 친숙한 설명을 표준 출력으로 인쇄합니다.

선택 목록을 작성 "$@"하고 진행 상황을 인쇄한 후에는 read여러 번의 시도 실패 후 종료되는 작은 루프에서 사용자 선택을 수행하는 동시에 입력의 유효성을 검사할 수 있습니다.

chk=$((($#<1)*5))                           #if not at least one choice quit
until [ "$((chk+=1))" -gt 5 ] && exit 1     #chks up to 5 times or quits
printf '\nSelect: '                         #prompts for each try
read -r c && [ -n "${c##*[!0-9]*}" ]        #fails if input not number or empty
do echo "Invalid selection."; done          #prints a notice and retries

shift마지막으로 불필요한 매개변수를 제거하고 다음을 호출 할 수 있습니다 $1.

shift "$((c-1))"; $1

앞에 0이 없는지 확인하는 것이 가장 좋습니다. shift사용자가 너무 높은 숫자를 선택하면 오류가 발생합니다.

[ "$((c=$(printf %.d "$c")))" -gt 0 ] || exit 
shift "$((c-1))" && $1

이것은 위치 배열을 매우 유용하게 만드는 숫자 선택 목록용입니다. 보다 일반적으로 다음 case문을 사용할 수 있습니다.

case "$choice" in
(pattern 1)  do as necessary for a match;;
(pattern 2)  do otherwise for this match;;
(pattern 3)  continue this wise for each;;
(*)          until there isn't a match  ;;
esac 

이는 많은 쉘을 에뮬레이트하는 이식 가능한 방법일 뿐입니다.(포함하다 bash)수년 전에 select소개된 진술이 제공될 것입니다.ksh

에서 man bash:

  • select 이름[in 단어];do 목록;done
    • 뒤에 오는 단어 목록이 확장되어 항목 목록이 생성됩니다. 확장된 단어 세트는 표준 오류로 인쇄되며 각 단어 앞에는 숫자가 붙습니다. 만약에연설에서생략된 위치 매개변수(또는 "$@")인쇄됩니다(아래 매개변수 참조). 그런 다음 프롬프트가 표시 $PS3되고 표준 입력에서 한 줄을 읽습니다.

답변3

에 있어야 합니다 ==. 그렇지 않으면 문자열 과 비교하는 대신 "$choice"==1 문자열 자체를 전달 하게 됩니다 . 문자열이 수신 되면 문자열이 비어 있지 않은 한 true로 평가됩니다.if$choice1[

$ foo="bar";  [ $foo ] && echo true
true
$ foo="";  [ "$foo" ] && echo true  ## echoes nothing

대괄호 외부에 test공백이 없으면 변수는 실제로 에 할당됩니다 =1. 표시하려면:

$ f==3
$ echo $f
=3
$ [ 10==12 ] && echo yes
yes

위에서 볼 수 있듯이 f==3변수 $f=3.

따라서 if블록에서 테스트되는 것은 항상 true로 평가되고 실행되는 비어 있지 않은 문자열입니다 if. 이것은 작동합니다:

if [ "$choice" == "1" ]
then
    baseinstall
fi

대안 으로 =또는==문자열 비교배쉬에서. 산술 비교를 원합니다.

if [ "$choice" -eq "1" ]
then
    baseinstall
fi

관련 정보