옵션 플래그가 있는 Bash 스크립트가 일관되지 않게 동작합니다.

옵션 플래그가 있는 Bash 스크립트가 일관되지 않게 동작합니다.

아래 코드는 mwe제가 생각하기에 일반적인 방법으로 플래그를 지정한 스크립트를 기반으로 한 것입니다. 그런데 아주 이상한 행동이 보입니다. 내가 입력하거나 매개 변수가 없다고 생각하면 반환 mwe -e됩니다 . 내가 입력하거나 그렇지 않다고 생각하면 반환 됩니다 . a로 끝나는 네 줄을 주석 처리하면 코드가 예상대로 작동합니다. 이는 루핑으로 인해 문제가 발생했음을 나타냅니다. 무슨 일인지 설명해 줄 수 있는 사람이 있나요?mwe -nno argmwe -kmwe -iargType"-"breaking#while

#!/bin/bash
foo=0
argType=`echo "$1" | cut -c 1`
while [ 1 -gt 0 ] ;   #
    do   #
        if [ $# -eq 0 ] ; then
            echo no arg
            exit
        elif [ "$argType" != "-" ] ; then
            #No more flags
            echo breaking
            break  #
        elif [ "$1" = "-n"  ] ; then
            foo=1
            shift
        elif [ "$1" = "-e"  ] ; then
            foo=2
            shift
        elif [ "$1" = "-i"  ] ; then
            foo=3
            shift
        elif [ "$1" = "-k"  ] ; then
            foo=4
            shift
        fi
done  #
echo This is foo:  $foo

답변1

세 번째 줄은 다음과 같아야합니다.

argType=$(printf "%s" "$1" | cut -c 1)

주석에서 언급했듯이 echo인수(예: 옵션)는 -e옵션 으로 해석되므로 더 나쁜 경우 -e는 에 전달되지 않습니다 cut.옵션 종료 플래그는 --다음에 사용할 수 없습니다.echo. 그런 다음 printf,어쨌든 일반적으로 이것이 더 좋습니다.

에 있으므로 bash@steeldriver의 제안을 받아 argType=${1:0:1}파이프 대신 사용할 수 있습니다(즉, 인수 1의 경우 문자 0으로 시작하여 1 문자 가져옴). 그러나 이는 POSIX 쉘에서는 사용할 수 없습니다.

백틱 대신 백틱을 선호합니다 $(). 백틱은 특히 중첩된 경우 가독성을 떨어뜨리기 때문입니다.

마지막으로 전송 중이므로 수정 후에도 시도하면 ./myscript -e -i결국 [ $# -eq 0 ]사실이 되어 실행이 종료되므로 주의하시기 바랍니다 exit. 의도적일 수도 있고 아닐 수도 있지만 echo결국 마지막 문제를 유발하지는 않습니다.

답변2

귀하의 질문에서 귀하가 원하는 것이 무엇인지 명확하지 않습니다!

어쨌든 마지막 매개변수에 해당하는 숫자를 원하는 것 같습니다.

#!/bin/bash
foo=0;

while [[ $# -gt 0 ]]; do
    case "${1}" in
        '-n')
            foo=1;
            shift
        ;;
        '-e')
            foo=2;
            shift
        ;;
        '-i')
            foo=3;
            shift
        ;;
        '-k')
            foo=4;
            shift
        ;;
        *)
            echo "Invalid flag";
            exit 1;
        ;;
    esac
done

echo "This is foo: $foo"

대신, 처리하기 전에 매개변수를 처리하고 검증하는 메커니즘을 원하는 경우 다음과 같은 것을 사용할 수 있습니다.

#!/bin/bash

inputf='';
outputf='';
text='';
format='';

while [[ $# -gt 0 ]];do
    case "${1}" in
        '-i')
            inputf="${2}";
            shift 2
        ;;
        '-o')
            outputf="${2}";
            shift 2
        ;;
        '-t')
            text="${2}";
            shift 2
        ;;
        '-f')
            format="${2}";
            shift 2
        ;;
    esac
done

관련 정보