带有选项标志的 bash 脚本行为不一致

带有选项标志的 bash 脚本行为不一致

下面的代码是基于mwe我编写的脚本的 mwe,其中我以我认为通常的方式指定了标志。但我看到了非常奇怪的行为。如果我输入mwe -e或者mwe -n它认为没有参数并返回no arg。如果我输入mwe -kmwe -i它认为argType不是"-"并返回breaking。如果我注释掉以 a 结尾的四行,#代码将按预期工作。这表明问题是由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 shell 中不可用。

也更喜欢$()而不是反引号,因为后者会损害可读性,尤其是在嵌套时。

最后,请注意您正在转移,因此,即使在更正之后,如果您尝试./myscript -e -i,最终[ $# -eq 0 ]将为 true 并且执行将由 终止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

相关内容