0

我正在尝试制作一个可以同时执行不同数量的程序(prog1、prog2、...prog5 甚至更多)的脚本。

它可以是 prog1 only , or prog1&prog2, or prog1&prog2&prog3, prog1&prog3&prog4&prog6&prog8

每个程序都可以使用不同的选项调用,并且会根据调用选项执行不同的操作。

例如 prog1 可以通过以下不同方式调用:

  1. prog1 -d "-f 10 -g 20"(-d 是一个选项,“-f 10 -g 20”是该特定选项的参数)
  2. prog1 -B
  3. prog1 -R "-l 2 -m 9"
  4. prog1 -S "10 20 30"

它也可以用它的组合来调用,比如: prog1 -d "-f 10 -g 20" -B -R "-l 2 -m 9"

我决定使用两阶段 getopt(嵌套 getopt)来解决这个问题。

在第一阶段,getopt 将处理用户作为脚本输入提供的不同程序。在第二阶段,getopt 将处理每个程序可以获得的不同选项和参数。

我的脚本如下:

#!/bin/bash

args=`getopt -o :v -l prog1:,prog2,prog3,prog4,prog5 -- "$@"`  # Here prog2,prog3..prog5 do not have a colon (:) to save some space but all of them will eventually get since when they are called they should have input arguments   
eval set -- "$args"
while true; do
case $1 in

      -v ) echo "VERBOSE"; shift;;
 --prog1 )
             echo "prog1 has been chosen with the following option:$2"

             args=`getopt -o :d:BR:S: -- "$@"`
               eval set -- "$args"
                 while true; do
                    case $1 in

                        -d )  echo "-d:$2"; shift 2;;
                        -B )  echo "-B"; shift;;
                        -R )  echo "-R:$2" ;shift 2 ;;
                        -S )  echo "-S:$2"; shift 2;;
                         --)  shift; break;; 
                     esac
                  done

             shift 2;; 

--prog2 )
             echo "similar things as in prog1";  shift
               ;;                           
--prog3 ) 
            echo "similar things as in prog1";  shift
               ;; 

--prog4 )
             echo "similar things as in prog1";  shift
               ;;                           
--prog5 ) 
            echo "similar things as in prog1";  shift
               ;;                         

     -- ) 
              shift; break;;
esac
done

当我将脚本运行为:my_script --prog1 -d "-f 10 -g 100" 它能够获取 -d 参数但不知何故进入无限循环,同时无法获取另一个参数“-f 10 -g 100”

理想情况下,脚本应该通过以下调用运行:

  1. my_script --prog1 -d "-f 10 -g 100" -R "-l 2 -m 9" --prog3 -M "-r 9 0.5 6" -F "-o 2 -q- 4" --prog5 .... etc

  2. my_script --prog1 -d "-f 10 -g 100".

  3. my_script --prog1 -d "-f 10 -g 100" -B --prog3 -F "-o 2 -q- 4"

  4. my_script --prog3 -F "-o 2 -q- 4" -M --prog2 -G

  5. ETC

您对如何克服这个问题有任何想法吗?

先感谢您

4

1 回答 1

0

您的问题部分在于您将 shell 的当前参数列表设置了两次:

args=$(getopt -o :v -l prog1:,prog2,prog3,prog4,prog5 -- "$@")
eval set -- "$args"  # First set of arguments
while true; do
case $1 in
      -v ) echo "VERBOSE"; shift;;
 --prog1 )
             echo "prog1 has been chosen with the following option:$2"
             args=`getopt -o :d:BR:S: -- "$@"`
             eval set -- "$args"    # Second set of arguments blows away the first

第二组选项击败了第一组。

“陷入循环”问题的原因不太明显。

这将很难解决。我认为您必须有一个循环来处理程序级选项;然后,对于要执行的每个程序,您将需要在第一个选项处理循环之后(不嵌套在其中)一个新循环:

args=$(getopt -o :v -l prog1:,prog2,prog3,prog4,prog5 -- "$@")
eval set -- "$args"
while true
do
    case $1 in
          -v ) echo "VERBOSE"; shift;;
     --prog1 )
               echo "prog1 has been chosen with the following options: $2"
               opts1="$2"
               shift 2;;
     --prog2 )
               echo "prog2 has been chosen with the following options: $2"
               opts2="$2"
               shift 2;;
     --prog3 )
               echo "prog3 has been chosen with the following options: $2"
               opts3="$2"
               shift 2;;
     --prog4 )
               echo "prog4 has been chosen with the following options: $2"
               opts4="$2"
               shift 2;;
     --prog5 )
               echo "prog5 has been chosen with the following options: $2"
               opts5="$2"
               shift 2;;
          -- ) 
               shift; break;;
    esac
done

if [ -n "$opts1" ]
then
     args=`getopt -o :d:BR:S: -- "$opts1"`
     eval set -- "$args"
     while true
     do
         case $1 in
         -d )  echo "-d:$2"; shift 2;;
         -B )  echo "-B"; shift;;
         -R )  echo "-R:$2" ;shift 2 ;;
         -S )  echo "-S:$2"; shift 2;;
         -- )  shift; break;; 
         esac
     done
     # Now execute prog1?
fi

# And similarly for $opts2 .. $opts5.

SSCCE

这是运行两个程序的工作代码。命令选项是无情的并行,但它们也不同。其中一项关键更改是从适当的已保存选项字符串中设置“每个程序”选项。它被缩减为只处理两个程序。我的 GNU 版本getopt没有安装在系统之前getopt,因此定义了getopt要运行的程序的变量。

GETOPT=/usr/gnu/bin/getopt

args=$($GETOPT -o :v -l prog1:,prog2: -- "$@")
eval set -- "$args"

while [ $# -gt 0 ]
do
    case $1 in
          -v ) echo "VERBOSE"; shift;;
     --prog1 )
               echo "prog1 has been chosen with the following options: $2"
               opts1="$2"
               shift 2;;
     --prog2 )
               echo "prog2 has been chosen with the following options: $2"
               opts2="$2"
               shift 2;;
          -- ) 
               shift; break;;
           * ) echo "$0: oops! $1 unexpected" >&2; exit 1;;
    esac
done
echo "$0: residual arguments: $@"

if [ -n "$opts1" ]
then
     args=$($GETOPT -o d:BR:S: -- $opts1)
     eval set -- "$args"
     while [ $# -gt 0 ]
     do
         case $1 in
         -d )  echo "prog1 -d:$2"; shift 2;;
         -B )  echo "prog1 -B";    shift 1;;
         -R )  echo "prog1 -R:$2"; shift 2;;
         -S )  echo "prog1 -S:$2"; shift 2;;
         -- )  shift; break;; 
          * )  echo "$0: oops processing prog1 - $1 unexpected" >&2; exit 1;;
         esac
     done
     echo "prog1 opts -- $@"
     # Now execute prog1?
fi

if [ -n "$opts2" ]
then
     args=$($GETOPT -o f:AT:G: -- $opts2)
     eval set -- "$args"
     while [ $# -gt 0 ]
     do
         case $1 in
         -f )  echo "prog2 -f:$2"; shift 2;;
         -A )  echo "prog2 -A";    shift 1;;
         -T )  echo "prog2 -T:$2"; shift 2;;
         -G )  echo "prog2 -G:$2"; shift 2;;
         -- )  shift; break;; 
          * )  echo "$0: oops processing prog2 - $1 unexpected" >&2; exit 1;;
         esac
     done
     echo "prog2 opts -- $@"
     # Now execute prog2?
fi

示例运行

$ sh multiopts.sh -v --prog2 "-f file -A -G garbage -T tag -- zero one" \
>                    --prog1="-S silence -R rubbish -B -d dog -- aleph null" -- abc def
VERBOSE
prog2 has been chosen with the following options: -f file -A -G garbage -T tag -- zero one
prog1 has been chosen with the following options: -S silence -R rubbish -B -d dog -- aleph null
multiopts.sh: residual arguments: abc def
prog1 -S:silence
prog1 -R:rubbish
prog1 -B
prog1 -d:dog
prog1 opts -- aleph null
prog2 -f:file
prog2 -A
prog2 -G:garbage
prog2 -T:tag
prog2 opts -- zero one
$
于 2013-03-16T00:35:34.900 回答