【问题标题】:Separating "flags" from "arguments" in bash script在 bash 脚本中将“标志”与“参数”分开
【发布时间】:2017-07-31 16:49:30
【问题描述】:

我正在使用一个遗留的 shell 脚本,用于测试二进制文件中的某些功能(即调用 nmobjdumpldd 等;并对结果进行一些解析)。当前的 shell 脚本非常“敏感”,而且很大,所以我想尽量减少对它所做的更改。

它目前首先检查参数的数量,每个参数都是一个路径,即:

if [ "$#" -lt 3 ]
then
  echo "Error. Invalid number of arguments."
  exit
fi

我想添加一些额外的参数及其长格式等效项,以禁用脚本内部的某些功能,而不会使上述测试无效,即:

-h | --help: Print shell usage and expected arguments.
-x | --xfer: Do some extra copy logic.
-d | --dry:  Do a dry-run, and don't actually change any files.

但是,我不希望将标志(即以连字符开头的参数)计为参数(即不影响将参数分配给 $1$2$3)。例如,以下当前是我的脚本的有效调用:

bash ./test.sh ./ ./out ./logs

我希望以下可能的调用也可以工作:

bash ./test.sh ./ ./out ./logs --dry
bash ./test.sh --xfer ./ ./out ./logs
bash ./test.sh --help
bash ./test.sh ./ --xfer ./out --dry ./logs

如何设置脚本来“过滤”以连字符(一个或两个)开头的参数,并保持对$1$2$3 的相同分配?

【问题讨论】:

  • 顺便说一句,如果非侵入性是您的首要目标,我会通过环境而不是命令行来接受这些选项。
  • @CharlesDuffy 好点。

标签: linux bash shell scripting


【解决方案1】:

您可以事后修改参数列表:

set -- one two three

因此,您可以将自己的解析放在顶部,并使用set -- 将您想要的任何参数放在所需的位置。


以过滤为例:

#!/usr/bin/env bash
#              ^^^^- not /bin/sh, as arrays are bash-only

help_and_exit() {
  local retval=${1:-1}
  cat <<EOF
${0##*/} [-d|--dry-run] [-x|--xfer] input output whatever

...put your extended help here...
EOF
  exit "$retval"
}

args=( )
dry_run=0; xfer=0
while (( $# )); do
  case $1 in
    -d|--dry)  dry_run=1 ;;
    -x|--xfer) xfer=1 ;;
    -h|--help) help_and_exit 0 ;;
    -*)        printf 'Unknown option: %q\n\n' "$1"
               help_and_exit 1 ;;
    *)         args+=( "$1" ) ;;
  esac
  shift
done
set -- "${args[@]}"

【讨论】:

  • 还有一个问题:我将如何修改它以便某些标志可以具有参数,并且我不希望 optarg 被解释为脚本本身的参数?即-d 需要一个参数跟随它。谢谢。
  • -d) dry_run=$2; shift ;; -- 见BashFAQ #35
  • 您也可以在那里处理 --dry=*-d* 与它们自己的 case 块(分别设置 dry_run=${1#*=}dry_run=${1#-d},对这些块进行排序以便调用 -d如果字符串为空,则支持-d*)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
相关资源
最近更新 更多