Ame*_*ina 192 bash zsh shell-script arguments
有没有什么简单的方法可以将命名参数传递(接收)给 shell 脚本?
例如,
my_script -p_out '/some/path' -arg_1 '5'
Run Code Online (Sandbox Code Playgroud)
并在内部my_script.sh将它们接收为:
# I believe this notation does not work, but is there anything close to it?
p_out=$ARGUMENTS['p_out']
arg1=$ARGUMENTS['arg_1']
printf "The Argument p_out is %s" "$p_out"
printf "The Argument arg_1 is %s" "$arg1"
Run Code Online (Sandbox Code Playgroud)
这在 Bash 或 Zsh 中可能吗?
ste*_*ver 224
如果您不介意仅限于单字母参数名称 ie my_script -p '/some/path' -a5,那么在 bash 中您可以使用内置的getopts,例如
#!/bin/bash
while getopts ":a:p:" opt; do
case $opt in
a) arg_1="$OPTARG"
;;
p) p_out="$OPTARG"
;;
\?) echo "Invalid option -$OPTARG" >&2
;;
esac
done
printf "Argument p_out is %s\n" "$p_out"
printf "Argument arg_1 is %s\n" "$arg_1"
Run Code Online (Sandbox Code Playgroud)
然后你可以做
$ ./my_script -p '/some/path' -a5
Argument p_out is /some/path
Argument arg_1 is 5
Run Code Online (Sandbox Code Playgroud)
有一个有用的Small getopts 教程,或者您可以help getopts在 shell 提示符下键入。
小智 58
我从drupal.org偷了这个,但你可以这样做:
while [ $# -gt 0 ]; do
case "$1" in
--p_out=*)
p_out="${1#*=}"
;;
--arg_1=*)
arg_1="${1#*=}"
;;
*)
printf "***************************\n"
printf "* Error: Invalid argument.*\n"
printf "***************************\n"
exit 1
esac
shift
done
Run Code Online (Sandbox Code Playgroud)
唯一的警告是您必须使用语法my_script --p_out=/some/path --arg_1=5。
小智 58
我使用这个脚本并像魅力一样工作:
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"
Run Code Online (Sandbox Code Playgroud)
用法
bash my_scripts.sh STEPS="ABC" REPOSITORY_NAME="stackexchange"
Run Code Online (Sandbox Code Playgroud)
控制台结果:
STEPS = ABC
REPOSITORY_NAME = stackexchange
Run Code Online (Sandbox Code Playgroud)
STEPS和REPOSITORY_NAME已准备好在脚本中使用。
参数的顺序无关紧要。
Hau*_*ing 40
可能最接近的语法是:
p_out='/some/path' arg_1='5' my_script
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 18
使用zsh,您将使用zparseopts:
#! /bin/zsh -
zmodload zsh/zutil
zparseopts -A ARGUMENTS -p_out: -arg_1:
p_out=$ARGUMENTS[--p_out]
arg1=$ARGUMENTS[--arg_1]
printf 'Argument p_out is "%s"\n' "$p_out"
printf 'Argument arg_1 is "%s"\n' "$arg_1"
Run Code Online (Sandbox Code Playgroud)
但是你会用myscript --p_out foo.
请注意,zparseopts它不支持缩写长选项或--p_out=foo像 GNUgetopt(3)那样的语法。
小智 15
我刚想出这个脚本
while [ $# -gt 0 ]; do
if [[ $1 == *"--"* ]]; then
v="${1/--/}"
declare $v="$2"
fi
shift
done
Run Code Online (Sandbox Code Playgroud)
传递它my_script --p_out /some/path --arg_1 5,然后在脚本中您可以使用$arg_1and $p_out。
小智 10
我发现cdmo 的解决方案是最好的,因为它不仅限于单个字母。稍作调整,它将消耗空格分隔的参数--url www.example.com,例如同义词参数-u=www.example.com。甚至可以解析标志参数:
while [ $# -gt 0 ]; do
case "$1" in
--url*|-u*)
if [[ "$1" != *=* ]]; then shift; fi # Value is next arg if no `=`
URL="${1#*=}"
;;
--file*|-f*)
if [[ "$1" != *=* ]]; then shift; fi
FILE="${1#*=}"
;;
--help|-h)
printf "Meaningful help message" # Flag argument
exit 0
;;
*)
>&2 printf "Error: Invalid argument\n"
exit 1
;;
esac
shift
done
Run Code Online (Sandbox Code Playgroud)
这个答案最初是对@cdmo 的回答的编辑(也感谢@Milkncookiez 的评论!),正如预期的那样被拒绝了,所以它是这样的:
#!/usr/bin/env bash
while [ $# -gt 0 ]; do
case "$1" in
-p|-p_out|--p_out)
p_out="$2"
;;
-a|-arg_1|--arg_1)
arg_1="$2"
;;
*)
printf "***************************\n"
printf "* Error: Invalid argument.*\n"
printf "***************************\n"
exit 1
esac
shift
shift
done
Run Code Online (Sandbox Code Playgroud)
以下调用都是等效的:
$ ./my-script.sh -a "lofa" -p "miez"
$ ./my-script.sh -arg_1 "lofa" --p_out "miez"
$ ./my-script.sh --arg_1 "lofa" -p "miez"
Run Code Online (Sandbox Code Playgroud)
使用变量时,可以确保它们具有"${p_out:-"default value"}"例如使用设置的默认值。