是否可以将命令行参数作为名称值对传递给 shell 脚本,例如
myscript action=build module=core
然后在我的脚本中,获取变量
$action
并处理它?
我知道 $1....等可用于获取变量,但不会像对那样是名称值。即使是这样,使用脚本的开发人员也必须注意以相同的顺序声明变量。我不要那个。
这对我有用:
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
STEPS和REPOSITORY_NAME已准备好在脚本中使用。
参数的顺序无关紧要。
高温高压
在 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 一样。我认为我从来没有认真使用过它(选项)。name1
name2
-k
name1
name2
name3
name4
bash
man 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
env action=build module=core myscript
你说你正在使用 tcsh。对于基于 Bourne 的 shell,您可以删除“env”,尽管将它留在那里是无害的。请注意,这适用于您从中运行命令的 shell,而不是用于实现myscript
.
如果您特别希望 name=value 对跟随命令名称,则需要在myscript
.
这是一个相当古老的问题,但仍然有效我还没有找到 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
扩展乔纳森的回答,这对我很有效:
#!/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