在bash脚本参数中是否允许使用连字符( - )?

时间:2016-07-08 08:23:15

标签: bash

我正在编写一个bash脚本,我希望从外部向我的脚本发送一个参数,该参数以连字符( - )开头,如此' -d'。

但是,当我执行脚本

时,我会收到以下警告
  

dirname:无效选项 - ' d'

我正在说警告,因为我可以看到我的脚本尽管如此仍在工作。但我也希望摆脱这些警告。有人可以帮忙吗?

为了进一步澄清,我正在执行这样的脚本 -

sh script.sh <param1> -d <param2>

从正在使用此参数的脚本中附加代码片段

case ${2} in
    -d|--days)      timeUnit="d";;
    -h|--hours)     timeUnit="h";;

3 个答案:

答案 0 :(得分:2)

这不是警告,这是一个错误。

如果您想将以短划线开头的文件名传递给dirname,那么您有两种选择:

dirname -- -d

dirname ./-d

根据您的调用行,我们可以推断您必须错误地将-d参数从脚本的参数列表中继到为脚本内部调用的dirname调用提供的参数列表

你可能在你的剧本中做了类似的事情:

dirname "$@"

或者

dirname "$2"

其中任何一个都会将-d参数传递给dirname

您需要正确解析脚本的参数,并仅将脚本的-d选项的选项值传递给dirname调用。此过程通常称为选项处理

以下是如何进行期权处理的示例:

dir='';
nonOpt=();
for ((i = 1; i <= $#; ++i)); do
    arg="${@:$i:1}";
    if [[ "$arg" == '--' ]]; then
        nonOpt+=("${@:$i+1}");
        break;
    elif [[ "$arg" == -?* ]]; then
        case "${arg:1}" in
            (d|dir)
                if [[ $i -eq $# ]]; then printf 'error: trailing -d option.\n' >&2; exit 1; fi;
                let ++i;
                dir="${@:$i:1}";
                ;;
            (h|help)
                printf 'script.sh [-h|--help] {param1} -d|--dir {dir}\n' >&2;
                exit 1;
                ;;
            (*)
                printf "error: invalid option: $arg.\\n" >&2;
                exit 1;
                ;;
        esac;
    else
        nonOpt+=("$arg");
    fi;
done;
if [[ ${#nonOpt[@]} -ne 1 ]]; then printf 'error: require 1 non-option argument.\n' >&2; exit 1; fi;
param1="${nonOpt[0]}";
if [[ "$dir" == '' ]]; then printf 'error: missing {dir}.\n' >&2; exit 1; fi;

dirname -- "$dir";

答案 1 :(得分:0)

shell脚本参数中允许使用连字符。

警告/错误是因为您将该参数传递给另一个不知道-d选项是什么的命令。

您应该look into using getopts来解析命令行参数。

答案 2 :(得分:0)

问题在于您对内部参数的处理方式。请注意,大多数程序将以连字符开头的参数视为一个选项,因此在传递实际参数之前,使用--正确结束选项并不重要。

在您的情况下,假设您将$1传递给dirname,它应该如下所示:

dir=`dirname -- "$1"`

或者如果它应该是shell的真正选项,那么你必须首先使用它并删除,shift将完成工作:

while [ $# -ne 0 ]; do
    case "$1" in
        -d)
             myoptionD=true
             shift
             ;;
        -*)
             echo "Unknown option: $1" >&2
             exit 2
             ;;
        *)
             break
             ;;
    esac
done

...或者您也可以使用getopt