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

在Bash getopts参数中保留特殊字符,bash,shell,escaping,special-characters,preserve,Bash,Shell,Escaping,Special Characters,Preserve,我在bashshell脚本库中有一个函数,它使用getopts接受参数。我想在其中一个参数中指定Bash命令。然后,该函数继续将此存储的命令用于某种目的,例如,以自动方式生成GNOME桌面启动器,并将此存储的命令指定为启动器的执行。如何以用户友好的方式保留命令中的特殊字符?我的意思是,以一种不要求用户转义指定命令中的特殊字符或执行其他异常困难的操作的方式 因此,函数的开头可能包含以下内容: OPTIND=1; while getopts ":i:o:" options; do case

我在bashshell脚本库中有一个函数,它使用getopts接受参数。我想在其中一个参数中指定Bash命令。然后,该函数继续将此存储的命令用于某种目的,例如,以自动方式生成GNOME桌面启动器,并将此存储的命令指定为启动器的执行。如何以用户友好的方式保留命令中的特殊字符?我的意思是,以一种不要求用户转义指定命令中的特殊字符或执行其他异常困难的操作的方式

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

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
作为函数参数给出的命令可以是以下内容:

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

您可以将公共参数解析与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

虽然如果我是这样做的,.

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

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