在 bash 中使用 getopts 处理可选参数

在 bash 中使用 getopts 处理可选参数

我有一个 bash 脚本,它处理带有可选参数的输入文件。脚本看起来像这样

#!/bin/bash
while getopts a:b:i: option
do
case "${option}"
in
a) arg1=${OPTARG};;
b) arg2=${OPTARG};;
i) file=${OPTARG};;
esac
done

[ -z "$file" ] && { echo "No input file specified" ; exit; }

carry out some stuff

该脚本运行良好,但我需要像这样指定输入文件

sh script.sh -a arg1 -b arg2 -i filename

我希望能够在没有选项的情况下调用脚本-i,就像这样

sh script.sh -a arg1 -b arg2 filename

当没有指定输入文件时仍然有错误消息。有没有办法做到这一点?

答案1

#!/bin/sh -

# Beware variables can be inherited from the environment. So
# it's important to start with a clean slate if you're going to
# dereference variables while not being guaranteed that they'll
# be assigned to:
unset -v file arg1 arg2

# no need to initialise OPTIND here as it's the first and only
# use of getopts in this script and sh should already guarantee it's
# initialised.
while getopts a:b:i: option
do
  case "${option}" in
    (a) arg1=${OPTARG};;
    (b) arg2=${OPTARG};;
    (i) file=${OPTARG};;
    (*) exit 1;;
  esac
done

shift "$((OPTIND - 1))"
# now "$@" contains the rest of the arguments

if [ -z "${file+set}" ]; then
  if [ "$#" -eq 0 ]; then
    echo >&2 "No input file specified"
    exit 1
  else
    file=$1 # first non-option argument
    shift
  fi
fi

if [ "$#" -gt 0 ]; then
  echo There are more arguments:
  printf ' - "%s"\n' "$@"
fi

我将 更改bash为因为该代码中sh没有任何特定内容。bash

答案2

我想扩展一下斯蒂芬·查泽拉斯很好的答案,以便使用巴什主义更多关于问题风格,即[ -z "$file" ] && { echo "No input file specified" ; exit; }——而不是使用如果

#!/bin/bash
unset -v file arg1 arg2

while getopts "a:b:i:" option; do
    case "$option" in
        a ) arg1="$OPTARG";;
        b ) arg2="$OPTARG";;
        i ) file="$OPTARG";;
        * ) exit 1;;
    esac
done

shift "$((OPTIND - 1))"

[ -z "$file" ] && [ "$#" -eq 0 ] && { echo "No input file" >&2; exit 1; }
[ -z "$file" ] && [ "$#" -gt 0 ] && { file="$1"; shift; }

echo "DEBUG: arg 1 is $arg1"
echo "DEBUG: arg 2 is $arg2"
echo "DEBUG: file  is $file"

[ "$#" -gt 0 ] && { echo "More arguments"; printf " - %s\n" "$@"; }

相关内容