9

是否可以将命令行参数作为名称值对传递给 shell 脚本,例如

myscript action=build module=core

然后在我的脚本中,获取变量 $action并处理它?

我知道 $1....等可用于获取变量,但不会像对那样是名称值。即使是这样,使用脚本的开发人员也必须注意以相同的顺序声明变量。我不要那个。

4

5 回答 5

14

这对我有用:

for ARGUMENT in "$@"
do
   KEY=$(echo $ARGUMENT | cut -f1 -d=)

   KEY_LENGTH=${#KEY}
   VALUE="${ARGUMENT:$KEY_LENGTH+1}"

   export "$KEY"="$VALUE"
done

echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"

用法

bash my_scripts.sh  STEPS="ABC" REPOSITORY_NAME="stackexchange"

控制台结果:

STEPS = ABC
REPOSITORY_NAME = stackexchange

STEPSREPOSITORY_NAME已准备好在脚本中使用。

参数的顺序无关紧要。

高温高压

于 2017-03-24T20:27:42.253 回答
4

在 Bourne shell 中,有一个很少使用的选项 ' ',它会自动将命令行中-k指定的任何值放入环境中。name=value当然,Bourne/Korn/POSIX shell 系列(包括 bash)也name=value对命令名之前的项目执行此操作:

name1=value1 name2=value2 command name3=value3 -x name4=value4 abc

在正常的 POSIX-shell 行为下,使用和在环境command中调用,并使用四个参数。在 Bourne(以及 Korn 和 bash,但不是 POSIX)shell选项下,它在环境中使用、、和调用,并且只有两个参数。手册页(如 参考资料中的)没有提到等效的,但它的工作方式与 Bourne 和 Korn shell 一样。我认为我从来没有认真使用过它(选项)。name1name2-kname1name2name3name4bashman bash-k-k

无法从脚本 ( command) 中得知环境变量是专门为该命令指定的;它们只是该脚本环境中的环境变量。

这是我所知道的最接近您所要求的方法。我认为 C shell 系列不存在任何等价物。我不知道有任何其他参数解析器可以name=value在命令行上从对设置变量。


有一些相当重要的警告(对于简单值相对容易,但很难处理包含 shell 元字符的值),您可以这样做:

case $1 in
(*=*) eval $1;;
esac

这不是 C shell 系列。有效地eval完成了外壳分配。

arg=name1=value1
echo $name1
eval $arg
echo $name1
于 2011-03-31T14:33:25.270 回答
1
env action=build module=core myscript

你说你正在使用 tcsh。对于基于 Bourne 的 shell,您可以删除“env”,尽管将它留在那里是无害的。请注意,这适用于您从中运行命令的 shell,而不是用于实现myscript.

如果您特别希望 name=value 对跟随命令名称,则需要在myscript.

于 2011-07-30T19:59:03.453 回答
1

这是一个相当古老的问题,但仍然有效我还没有找到 cookie cut 解决方案。我结合了上面的答案。为了我的需要,我创建了这个解决方案;这甚至适用white space于参数的值。

将此另存为argparse.sh

#!/bin/bash

: ${1?
  'Usage:
  $0 --<key1>="<val1a> <val1b>" [ --<key2>="<val2a> <val2b>" | --<key3>="<val3>" ]'
}

declare -A args
while [[ "$#" > "0" ]]; do
  case "$1" in 
    (*=*)
        _key="${1%%=*}" &&  _key="${_key/--/}" && _val="${1#*=}"
        args[${_key}]="${_val}"
        (>&2 echo -e "key:val => ${_key}:${_val}")
        ;;
  esac
  shift
done
(>&2 echo -e "Total args: ${#args[@]}; Options: ${args[@]}")

## This additional can check for specific key
[[ -n "${args['path']+1}" ]] && (>&2 echo -e "key: 'path' exists") || (>&2 echo -e "key: 'path' does NOT exists");

@Example:注意,脚本的参数可以有可选的前缀--

./argparse.sh --x="blah"
./argparse.sh --x="blah" --yy="qwert bye"
./argparse.sh x="blah" yy="qwert bye"

此脚本的一些有趣用例:

./argparse.sh --path="$(ls -1)"
./argparse.sh --path="$(ls -d -1 "$PWD"/**)"

以上脚本创建为 gist,参考:argparse.sh

于 2020-08-09T20:36:01.740 回答
0

扩展乔纳森的回答,这对我很有效:

#!/bin/bash
if [ "$#" -eq "0" ]; then
  echo "Error! Usage: Remind me how this works again ..."
  exit 1
fi

while [[ "$#" > "0" ]]
do
  case $1 in
    (*=*) eval $1;;
  esac
shift
done
于 2016-02-03T06:14:00.353 回答