保留Bash getopts参数中的特殊字符

时间:2013-09-25 16:40:38

标签: bash shell escaping special-characters preserve

我在Bash shell脚本库中有一个函数,它使用getopts接受参数。我想在其中一个参数中指定一个Bash命令。然后,该函数继续将此存储的命令用于一个或另一个目的(例如,以自动方式生成GNOME桌面启动器,并将此存储的命令指定为启动器的执行)。我怎样才能以用户友好的方式保存命令中的特殊字符(并且,我的意思是,这种方式不需要用户在指定的命令中转义特殊字符或者做一些异常困难的事情)? / p>

因此,函数的开头可能包含以下内容:

OPTIND=1; while getopts ":i:o:" options; do
    case "${options}" in
        i)
            command_1="${OPTARG}"
            ;;
        o)
            fileName_1="${OPTARG}"
            ;;
        \?)
            echo "invalid option -"${OPTARG}""
            return
            ;;
        :)
            echo "option -"${OPTARG}" requires an argument"
            return
            ;;
    esac

作为函数参数给出的命令可以是如下内容:

echo "hello" | festival --tts

2 个答案:

答案 0 :(得分:0)

您可以将常见的参数解析与getopts混合使用:

OPTIND=1
while :; do
    case "${!OPTIND}" in
    --tts)
        TTS=true
        (( ++OPTIND ))
        ;;
    --another-with-arg)
        (( ++OPTIND ))
        # Perhaps add a check as well if optarg is valid.
        ANOTHER=${!OPTIND}
        (( ++OPTIND ))
        ;;
    *)
        if getopts ":ai:o:" options; then
            case "${options}" in
            i)
                command_1="${OPTARG}"
                ;;
            o)
                fileName_1="${OPTARG}"
                ;;
            \?)
                echo "invalid option -"${OPTARG}""
                return
                ;;
            :)
                echo "option -"${OPTARG}" requires an argument"
                return
                ;;
            esac
        else
            return
        fi
        ;;
    esac
done

虽然如果我在,I wouldn't use getopts at all

答案 1 :(得分:0)

我的解释是,您希望用户能够编写如下内容:

my_script -i echo "hello" | festival --tts

并将-i之后的整个序列(包括管道字符)作为参数接受。

不幸的是,这真的不可能。被调用的脚本无法实现,因为在调用脚本之前已经解析了整个命令行。

当然,用户可以写:

my_script -i 'echo "hello" | festival --tts'

但是如果所需的命令行包含撇号,那将需要英勇的努力。

“通常”方法(例如,由find实用程序的-exec选项使用)是接受命令行参数,直到找到;。当然,;需要被转义,就像任何管道或其他shell元字符一样。

您可以做的一件事是提供一个单独的选项,可能是-I,它从stdin读取一行并将其用作命令。这对于难以引用的复杂命令行来说会很方便,但如果实用程序还想将stdin用于其他目的,则会有点尴尬。有了这个,用户可以输入:

my_script -I file <<"EOF"
very_complicated_command 'with$x' "$all kinds of punctuation" 2> logfile | even_pipes
EOF