Bash脚本:要求每个选项参数最多出现一次

时间:2021-10-21 20:24:42

I am writing a script in unix, which will take options as parameter as shown:

我在unix中编写一个脚本,它将选项作为参数显示如下:

./command -pers

The options allowed are p, e, r, s and can be in any order and are optional also. Example, these are correct syntax: ./command -e, ./command -sr, ./command -pes, but this one is incorrect ./command -pep, ./command -ssr. Repetition of option is not allowed, but atleast one option is required.

允许的选项是p,e,r,s,可以是任何顺序,也是可选的。例如,这些是正确的语法:./ command-e,。/ command -sr,。/ command -pes,但这个不正确./command -pep,。/ command -ssr。不允许重复选项,但至少需要一个选项。

For the same I have used regular expression, but it is not avoiding repetition.

对于同样的我使用正则表达式,但它不是避免重复。

But it is allowing repetition. Please tell what is wring with the expression.

但它允许重复。请告诉我们表达的内容是什么。

[[ $1 =~ ^-[p{0,1}r{0,1}s{0,1}e{0,1}]{1,4}$ ]] || { echo "$MSG_INCORRECT_USAGE"; }

3 个解决方案

#1


1  

You can use a script opt.sh like this to avoid processing each passed option more than once:

您可以像这样使用脚本opt.sh,以避免多次处理每个传递的选项:

#!/bin/bash

while getopts "pers" opt; do
  [[ -n ${!opt} ]] && { echo "Error: $opt already processed"; exit 1; } || declare $opt=1

  case $opt in
    p) echo "processing p!" ;;
    e) echo "processing e!" ;;
    r) echo "processing r!" ;;
    s) echo "processing s!" ;;
    \?) echo "Invalid option: -$OPTARG" ;;
  esac
done

Testing:

测试:

bash ./opt.sh -srr
processing s!
processing r!
Error: r already processed

bash ./opt.sh -pep
processing p!
processing e!
Error: p already processed

bash ./opt.sh -pers
processing p!
processing e!
processing r!
processing s!

#2


1  

#!/bin/bash

while getopts "pers" OPTION; do
        echo $OPTION
done

Results:

结果:

$ bash test.sh -pers
p
e
r
s

Replace echo $OPTION with a case statement and report errors if an option appears twice. Example:

将echo $ OPTION替换为case语句,并在选项出现两次时报告错误。例:

#!/bin/bash

unset OPT_P OPT_E OPT_R OPT_S

while getopts "pers" OPTION; do
    case $OPTION in
    p)
        if [ $OPT_P ]; then
            echo "-p appeared twice"
            exit 64
        else
            OPT_P="true"
        fi
        ;;
    #... and so on ...
    \?)
        echo "Unrecognized option $OPTION"
        exit 64
        ;;
done

#3


0  

arg0=$(basename $0 .sh)
error() { echo "$arg0: $*" >&2; exit 1; }
usage() { echo "Usage: $arg0 [-pers]" >&2; exit 1; }

p_flag=
e_flag=
r_flag=
s_flag=

while getopts pers arg
do
    case "$arg" in
    (e) [ -z "$e_flag" ] || error "-e flag repeated"
        e_flag=1;;
    (p) [ -z "$p_flag" ] || error "-p flag repeated"
        p_flag=1;;
    (r) [ -z "$r_flag" ] || error "-r flag repeated"
        r_flag=1;;
    (s) [ -z "$s_flag" ] || error "-s flag repeated"
        s_flag=1;;
    (*) usage;;
    esac
done

shift $(($OPTIND - 1))

[ -z "$e_flag$p_flag$r_flag$s_flag" ] && error "You must specify one of -e, -p, -r, -s"
[ $# = 0 ] || error "You may not specify any non-option arguments"

…process the code for each option that was set…

If you need to process the options in the sequence they're given, then you need to record the order in which they arrive. Use an array:

如果您需要按顺序处理选项,则需要记录它们到达的顺序。使用数组:

flags=()

before the loop, and

在循环之前,和

flags+=("$arg")

after the esac. The processing can then process each element of the $flags in sequence.

在esac之后。然后,处理可以按顺序处理$标志的每个元素。

for flag in "${flags[@]}"
do
    …processing for the particular flag…
done

#1


1  

You can use a script opt.sh like this to avoid processing each passed option more than once:

您可以像这样使用脚本opt.sh,以避免多次处理每个传递的选项:

#!/bin/bash

while getopts "pers" opt; do
  [[ -n ${!opt} ]] && { echo "Error: $opt already processed"; exit 1; } || declare $opt=1

  case $opt in
    p) echo "processing p!" ;;
    e) echo "processing e!" ;;
    r) echo "processing r!" ;;
    s) echo "processing s!" ;;
    \?) echo "Invalid option: -$OPTARG" ;;
  esac
done

Testing:

测试:

bash ./opt.sh -srr
processing s!
processing r!
Error: r already processed

bash ./opt.sh -pep
processing p!
processing e!
Error: p already processed

bash ./opt.sh -pers
processing p!
processing e!
processing r!
processing s!

#2


1  

#!/bin/bash

while getopts "pers" OPTION; do
        echo $OPTION
done

Results:

结果:

$ bash test.sh -pers
p
e
r
s

Replace echo $OPTION with a case statement and report errors if an option appears twice. Example:

将echo $ OPTION替换为case语句,并在选项出现两次时报告错误。例:

#!/bin/bash

unset OPT_P OPT_E OPT_R OPT_S

while getopts "pers" OPTION; do
    case $OPTION in
    p)
        if [ $OPT_P ]; then
            echo "-p appeared twice"
            exit 64
        else
            OPT_P="true"
        fi
        ;;
    #... and so on ...
    \?)
        echo "Unrecognized option $OPTION"
        exit 64
        ;;
done

#3


0  

arg0=$(basename $0 .sh)
error() { echo "$arg0: $*" >&2; exit 1; }
usage() { echo "Usage: $arg0 [-pers]" >&2; exit 1; }

p_flag=
e_flag=
r_flag=
s_flag=

while getopts pers arg
do
    case "$arg" in
    (e) [ -z "$e_flag" ] || error "-e flag repeated"
        e_flag=1;;
    (p) [ -z "$p_flag" ] || error "-p flag repeated"
        p_flag=1;;
    (r) [ -z "$r_flag" ] || error "-r flag repeated"
        r_flag=1;;
    (s) [ -z "$s_flag" ] || error "-s flag repeated"
        s_flag=1;;
    (*) usage;;
    esac
done

shift $(($OPTIND - 1))

[ -z "$e_flag$p_flag$r_flag$s_flag" ] && error "You must specify one of -e, -p, -r, -s"
[ $# = 0 ] || error "You may not specify any non-option arguments"

…process the code for each option that was set…

If you need to process the options in the sequence they're given, then you need to record the order in which they arrive. Use an array:

如果您需要按顺序处理选项,则需要记录它们到达的顺序。使用数组:

flags=()

before the loop, and

在循环之前,和

flags+=("$arg")

after the esac. The processing can then process each element of the $flags in sequence.

在esac之后。然后,处理可以按顺序处理$标志的每个元素。

for flag in "${flags[@]}"
do
    …processing for the particular flag…
done