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

Leo*_*mon 3 bash for

下面的代码是基于mwe我编写的脚本的 mwe,我在其中以我认为通常的方式指定标志。但我看到了非常奇怪的行为。如果我输入mwe -emwe -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
Run Code Online (Sandbox Code Playgroud)

Qua*_*odo 6

第三行应该是

argType=$(printf "%s" "$1" | cut -c 1)
Run Code Online (Sandbox Code Playgroud)

如评论中所述,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不会被触发。