【问题标题】:Search for one command line parameter before the rest先搜索一个命令行参数
【发布时间】:2016-03-15 18:29:36
【问题描述】:

我正在使用getopt 读取我的命令行参数,我正在使用. 读取配置文件:

test.sh:

#!/bin/bash

set -- `getopt C:a:b:c: "$@"`

C="default.cfg"
. $C

while [ $# -gt 0 ]; do
    case "$1" in
    -a) cfg1="$2"; shift;;
    -b) cfg2="$2"; shift;;
    -c) cfg3="$2"; shift;;
    -C) C="$2"; #you'll see what this is for later
        shift;;
    --) shift;
        break;;
    -*) echo "invalid option";
        exit 1;;
    *) break;;
    esac
    shift
done

echo "cfg1 = $cfg1"
echo "cfg2 = $cfg2"
echo "cfg3 = $cfg3"

exit 0

default.cfg::

cfg1=hello
cfg2=there
cfg3=friend

这一切都按预期工作:

$ ./test.sh
cfg1 = hello
cfg2 = there
cfg3 = friend
$ ./test.sh -b optional
cfg1 = hello
cfg2 = optional
cfg3 = friend

这个问题是我希望以下列方式优先配置配置:

  1. 命令行中给出的选项
  2. -C 选项定义的配置文件中定义的选项
  3. 默认配置文件中定义的选项

如果我有这个:

test.cfg:

cfg1=custom_file_1
cfg2=custom_file_2

我想得到这个:

$ ./test.sh -b command_line -C test.cfg
cfg1 = custom_file_1
cfg2 = command_line
cfg3 = friend

我只是不知道如何加载默认配置文件,然后搜索-C的选项,然后加载自定义配置文件,覆盖默认值,然后再次搜索命令行参数并再次覆盖配置.我对 shell 脚本很陌生,所以如果我遗漏了一些明显的东西,请原谅我。

【问题讨论】:

    标签: bash shell


    【解决方案1】:

    您可以预处理参数并提取您要查找的值:

    #!/bin/bash
    args=$(getopt C:a:b:c: "$@")
    eval set -- $args
    
    conf="default.cfg"
    source "$conf"
    
    # pre-process the arguments and see if we can find -C    
    found=0
    for opt in "$@"; do
        if [[ $found -eq 1 ]] && [[ -f "$opt" ]]; then
            source "$opt"
            break
        fi
        if [[ "$opt" == "-C" ]]; then
            found=1
        fi
    done
    
    while [ $# -gt 0 ]; do
        case "$1" in
        -a) cfg1="$2"; shift;;
        -b) cfg2="$2"; shift;;
        -c) cfg3="$2"; shift;;
        -C) shift;; #don't do anything with this
        --) shift;
        break;;
        -*) echo "invalid option";
            exit 1;;
        *) break;;
        esac
        shift
    done
    
    echo "cfg1 = $cfg1"
    echo "cfg2 = $cfg2"
    echo "cfg3 = $cfg3"
    
    exit 0
    

    【讨论】:

    • 值得一提的是,您应该使用getopts,它是一个属于 POSIX 规范的内置 shell,尽管语法略有不同。 getopt 可能是一个更旧的外部实用程序,或者是一个支持长选项的较新的 Gnu 版本。如果你想依赖 Gnu 版本,你应该测试它。
    【解决方案2】:

    要覆盖变量,请尝试替换:

    -C) C="$2";
    

    与:

    -C) . "$2";
    

    然后用 :

    调用它
    ./test.sh -C test.cfg -a command_line1 -b command_line2
    

    更新:

    对于任何顺序的选项,你可以试试这个:

    C="default.cfg"
    . $C
    
    while getopts C:a:b:c: OPTION
      do
        case $OPTION in
          a) cfg1_override=$OPTARG;;
          b) cfg2_override=$OPTARG;;
          c) cfg3_override=$OPTARG ;;
          C) . $OPTARG;;
          -) break;;
          -*) echo "invalid option";
              exit 1;;
          *) break;;
        esac
      done
    shift $(($OPTIND - 1))
    
    cfg1="${cfg1_override-${cfg1}}"
    cfg2="${cfg2_override-${cfg2}}"
    cfg3="${cfg3_override-${cfg3}}"
    
    echo "cfg1 = $cfg1"
    echo "cfg2 = $cfg2"
    echo "cfg3 = $cfg3"
    
    exit 0
    

    基于Is it possible to specify the order getopts conditions are executed?

    【讨论】:

    • 那么如果我执行./test.sh -a command_line1 -b command_line2 -C test.cfg会发生什么?
    • 我更新了我的答案。您必须添加 -̀C test.cfg`作为第一个参数。
    • 所以这个选项要求 -C 是命令行的第一个选项?我希望有一个不会对用户施加这种限制的解决方案。
    • 例如与find 命令相同(尝试̀find -type f .)。您还可以在脚本中重新排序参数。
    • 我该怎么做?如果我可以在脚本中重新排序参数,我想我可以很容易地搜索 -C 并加载它,然后运行其余选项。
    【解决方案3】:

    第一个源 default.cfg。 比扫描您的选项以查找 -C 选项。找到后处理这个。 最后使用 getopts 并在 getopts 期间找到它时跳过 -C。

    【讨论】:

      猜你喜欢
      • 2019-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 1970-01-01
      • 2018-11-25
      • 2013-02-23
      • 1970-01-01
      相关资源
      最近更新 更多