指定命令行参数,如shell脚本的name=value对

k4emjkb1  于 2023-02-05  发布在  Shell
关注(0)|答案(5)|浏览(172)

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

myscript action=build module=core

然后在我的脚本中,获取像$action这样的变量并处理它?
我知道$1 ......等等可以用来获取变量,但是不会像对那样命名值。即使它们是对,那么使用脚本的开发人员将不得不注意以相同的顺序声明变量。我不希望这样。

bfhwhh0e

bfhwhh0e1#

这对我很有效:

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

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

   export "$KEY"="$VALUE"
done

# use here your expected variables
echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"

用途

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

控制台结果:

STEPS = ABC
REPOSITORY_NAME = stackexchange

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

参数的顺序并不重要。

更改日志

  • 版本1.0.0
8mmmxcuj

8mmmxcuj2#

在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调用,并使用四个参数。(以及Korn和bash,但不包括POSIX)shell -k选项,它是通过name1name2name3、和name4,并且只有两个参数。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
bvk5enib

bvk5enib3#

env action=build module=core myscript

您说您使用的是tcsh。对于基于Bourne的shell,您可以删除“env”,尽管将其留在那里是无害的。注意,这适用于您从中运行命令的shell,而不是用于实现myscript的shell。
如果您特别希望name=value对跟在命令名后面,则需要在myscript中做一些工作。

irlmq6kh

irlmq6kh4#

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

jc3wubiy

jc3wubiy5#

根据乔纳森的回答,我觉得这句话很管用:

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

相关问题