为shell脚本指定名称=值对等命令行参数

时间:2011-03-31 12:00:00

标签: shell tcsh

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

myscript action=build module=core

然后在我的脚本中,获取变量之类的 $action并处理它?<​​/ p>

我知道$ 1 ....等等可以用来获取变量,但是不会像对子那样是名字值。即使它们是,但使用该脚本的开发人员必须负责以相同的顺序声明变量。我不希望这样。

5 个答案:

答案 0 :(得分:7)

这对我有用:

for ARGUMENT in "$@"
do

    KEY=$(echo $ARGUMENT | cut -f1 -d=)
    VALUE=$(echo $ARGUMENT | cut -f2 -d=)   

    case "$KEY" in
            STEPS)              STEPS=${VALUE} ;;
            REPOSITORY_NAME)    REPOSITORY_NAME=${VALUE} ;;     
            *)   
    esac    


done

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

用法

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

控制台结果:

STEPS = ABC
REPOSITORY_NAME = stackexchange

STEPS REPOSITORY_NAME 已准备好在脚本中使用。

参数的顺序无关紧要。

HTH

答案 1 :(得分:3)

在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在环境中使用name1name2调用,并带有四个参数。在Bourne(和Korn和bash,但不是POSIX)shell -k选项下,使用name1name2name3name4调用它环境和两个论点。 bash手册页(如man bash中所述)未提及-k的等效内容,但它的工作方式与Bourne和Korn shell相同。 我认为我没有认真使用它(-k选项)。

无法在脚本(command)内告知环境变量仅为此命令指定;它们只是该脚本环境中的环境变量。

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


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

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

这不是C shell系列。 eval有效地进行了shell分配。

arg=name1=value1
echo $name1
eval $arg
echo $name1

答案 2 :(得分:1)

env action=build module=core myscript

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

如果您特别希望name = value对遵循命令名称,则需要在myscript内进行一些工作。

答案 3 :(得分:1)

这是一个很老的问题,但仍然有效 我还没有找到Cookie削减解决方案。我结合了以上答案。为了我的需要,我创建了这个解决方案。即使在参数值中使用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");

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

./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"/**)"

以上创建为要点的脚本,请参考:argparse.sh

答案 4 :(得分:0)

根据Jonathan的回答,这对我很有用:

#!/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