【问题标题】:Bash: handling mass argumentsBash:处理大量参数
【发布时间】:2016-06-20 08:05:44
【问题描述】:

无论标志的顺序如何,我都希望能够处理给定标志的多个参数。大家觉得这样可以接受吗?有什么改进吗?

所以:

$ ./script -c opt1 opt2 opt3 -b foo

opt1 opt2 opt3
foo

代码:

echo_args () {
    echo "$@"
}


while (( $# > 0 )); do
    case "$1" in
        -b)
            echo $2
        ;;

        -c|--create)
            c_args=()

            # start looping from this flag
            for arg in ${@:2}; do
                [ "${arg:0:1}" == "-" ] && break
                c_args+=("$arg")
            done

            echo_args "${c_args[@]}"
        ;;

        *)
            echo "huh?"
        ;;
    esac

    shift 1
done

【问题讨论】:

  • 您可以做一些类似于 gcc 在将参数传递给例如时所做的事情。链接器:-Wl,arg1,arg2,arg3 即从空格作为分隔符切换到逗号。
  • 一些程序接受重复的标志:-c opt1 -c opt2 -c opt3 -b foo.
  • 是的,不使用 IFS 分隔符可以让我只传递下一个参数“$2”然后处理它,但我想让它类似于某些 GNU 命令的工作方式。
  • 什么 Gnu 命令接受多个参数到一个标志
  • cp-t 标志例如。

标签: bash positional-operator


【解决方案1】:

getopts 实用程序应从参数列表中检索选项和选项参数。

$ cat script.sh

cflag=
bflag=
while getopts c:b: name
do
    case $name in
    b)    bflag=1
          bval="$OPTARG";;
    c)    cflag=1
          cval="$OPTARG";;
    ?)   printf "Usage: %s: [-c value] [-b value] args\n" $0
          exit 2;;
    esac
done
if [ ! -z "$bflag" ]; then
    printf 'Option -b "%s" specified\n' "$bval"
fi
if [ ! -z "$cflag" ]; then
    printf 'Option -c "%s" specified\n' "$cval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"

注意准则 8: 当多个选项参数被指定为跟在单个选项之后,它们应该作为单个参数呈现,在该参数中使用逗号或在该参数中使用 来分隔它们。

$ ./script.sh -c "opt1 opt2 opt3" -b foo

Option -b "foo" specified
Option -c "opt1 opt2 opt3" specified
Remaining arguments are:

标准链接如下:

【讨论】:

  • 我知道这一点,但我想模拟一些 GNU 命令的行为(即,不将参数分组为单个字符串)。你会推荐这个而不是我的方法吗?
  • 顺便说一句,您没有将各种printf 命令放在case 命令中的任何特殊原因?
  • 您的方法很好,但不符合标准,仅此而已。
  • 代码是从 getopts 手册页复制的,经过改编(只是一点点),并快速测试,这就是 printf 位于这些位置的原因。
  • 啊,好的。我会接受这个作为答案。感谢您的帮助!
【解决方案2】:

我在 cmets 中注意到您不想使用其中任何一个。您可以做的是将所有参数设置为字符串,然后使用循环对它们进行排序,取出您想要设置为切换的参数并使用 if 语句对其进行排序。有点野蛮,但可以做到。

#!/bin/bash

#set all of the arguments as a variable
ARGUMENTS=$@

# Look at each argument and determine what to do with it.
for i in $ARGUMENTS; do
    # If the previous loop was -b then grab the value of this argument
    if [[ "$bgrab" == "1" ]]; then
        #adds the value of -b to the b string
        bval="$bval $i"
        bgrab="0"
    else
        # If this argument is -b, prepare to grab the next argument and assign it
        if [[ "$i" == "-b" ]]; then
            bgrab="1"
        else
            #Collect the remaining arguments into one list per your example
              RemainingArgs="$RemainingArgs $i"
        fi
    fi
done

echo "Arguments: $RemainingArgs"
echo "B Value: $bval"

我在我的很多脚本中都使用了类似的东西,因为有大量的参数可以输入其中的一些,并且脚本需要查看每个参数以弄清楚要做什么。它们可能出现故障或根本不存在,但代码仍然必须工作。

【讨论】:

  • 但这只能与重复标志一起使用:./script -b value1 -b value2,在这种情况下,只需将$2shift 命令一起使用似乎更简单,不是吗?
  • 我没有太多机会使用shift 命令。尽管您可以添加仅将 -b 的值添加到字符串中的行。 (补充)就像我说的,我使用上面的这种类型的脚本来排序和解析开关和参数。
  • 您为什么使用完全损坏的for i in $ARGUMENTS;,而不是for i in "$@";
  • 我不喜欢在脚本头部之外使用未定义的变量。我在所有脚本中都坚持严格的方法,无论大小,就像这个一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
  • 2022-09-29
  • 2011-05-10
  • 2017-02-09
  • 1970-01-01
相关资源
最近更新 更多