如何编写以任何给定顺序获取参数的bash脚本?

时间:2016-10-07 10:28:46

标签: bash shell parameter-passing

我想知道我应该使用什么原则来编写一个以任何给定顺序获取其参数的bash脚本。 例如:

  • 让我们为我的剧本命名: script.sh
  • 让我们说我希望它采取 no或至少两个参数
  • 现在假设一个标准参数是 -f ,它指定下一个参数是我应该处理的文件的名称。
  • 再次假设给定文件的名称为: input.dat
  • 最后(为了示例),假设我可以添加的最后两个参数命名为: -print -delete

我在这里问的是:

  

我是否可以使用特定的方式(甚至是编程技术),以便可以按任何给定的顺序传递参数(除了文件名应始终遵循 -f 参数这一事实?

以下是一些调用示例:

  1. ./ script.sh -f input.dat -print
  2. ./ script.sh -print -f input.dat
  3. 以上两次执行应该产生相同的例子!

      

    在回答时,请请记住,真正的问题有更多的参数和不同的结果!

2 个答案:

答案 0 :(得分:0)

这是我为实现这个目的所写的脚本:

#!/bin/bash

# The code below was written to replace the -print and -delete options for
# -p and -d respectively, because getopts can't handle long args, I suggest
# you only use arguments of single letters to make your code more simple, but if 
# you can't avoid it then this is a workaround

for ARGS in "$@"; do
shift
        case "$ARGS" in
                "-print") set -- "$@" "-p" ;;
                "-delete") set -- "$@" "-d" ;;
                *) set -- "$@" "$ARGS"
        esac
done
# getopts works like this: you put all your arguments between single quotes
# if you put a ':' character after the argument letter (just like I did with
# the 'f' letter in the example below), it means this argument NEEDS an extra
# parameter. If you just use letters without the ':' it means it doesn't need
# anything but the argument itself (it's what I did for the '-p' and '-d' options)

while getopts 'f:pd' flag; do
        case "${flag}" in
                f) FILE=${OPTARG} ;;
                p) COMMAND="print" ;;
                d) COMMAND="delete" ;;
        esac
done

echo "$COMMAND $FILE"

以下是运行的例子:

$ ./script.sh -f filename -print
print filename
$ ./script.sh -print -f filename
print filename
$ ./script.sh -f filename -delete
delete filename
$ ./script.sh -delete -f filename
delete filename

答案 1 :(得分:0)

以前的解决方案是一个很好的起点,我尝试使用它是因为它能够接受一个标志的多个参数,而且我认为这是一种更好的样式(也减少了未使用的变量):

#!/bin/bash
while [ $# -gt 0 ]; do
    case "$1" in
        --file|-f) filename=$2 ; shift;;
        --print|-p) printCommand ;;
        --delete|-d) deleteCommand ;;
        *) break
    esac
shift
done

此外,音符移位可以以移动数作为参数,这有助于保持其整洁。例如:

--two-files) filename1=$2; filename2=$3; shift 2;;