Passing named arguments as array in shell script Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) 2019 Community Moderator Election Results Why I closed the “Why is Kali so hard” questionPassing arguments with quotes and doublequotes to bash scriptPassing arguments to su-provided shellPassing named arguments to shell scriptsPassing arguments from a file to a bash scriptPassing paths with spaces as argumentspassing composed commands as argumentsPassing inline arguments to shell script being executed on HDFSPassing arguments to awk scriptPassing directory from command line to shell scriptPassing arguments from one script to another
What is the meaning of the new sigil in Game of Thrones Season 8 intro?
What is a non-alternating simple group with big order, but relatively few conjugacy classes?
How to answer "Have you ever been terminated?"
illegal generic type for instanceof when using local classes
How widely used is the term Treppenwitz? Is it something that most Germans know?
What does the word "veer" mean here?
What LEGO pieces have "real-world" functionality?
Is pollution the main cause of Notre Dame Cathedral's deterioration?
String `!23` is replaced with `docker` in command line
Why are there no cargo aircraft with "flying wing" design?
Echoing a tail command produces unexpected output?
The logistics of corpse disposal
Dating a Former Employee
Align equal signs while including text over equalities
Storing hydrofluoric acid before the invention of plastics
Why aren't air breathing engines used as small first stages
Why do we bend a book to keep it straight?
List *all* the tuples!
How can I make names more distinctive without making them longer?
Coloring maths inside a tcolorbox
Why are Kinder Surprise Eggs illegal in the USA?
What's inside the kernel part of virtual memory of 64 bit linux processes?
How does the particle を relate to the verb 行く in the structure「A を + B に行く」?
Identify plant with long narrow paired leaves and reddish stems
Passing named arguments as array in shell script
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)
2019 Community Moderator Election Results
Why I closed the “Why is Kali so hard” questionPassing arguments with quotes and doublequotes to bash scriptPassing arguments to su-provided shellPassing named arguments to shell scriptsPassing arguments from a file to a bash scriptPassing paths with spaces as argumentspassing composed commands as argumentsPassing inline arguments to shell script being executed on HDFSPassing arguments to awk scriptPassing directory from command line to shell scriptPassing arguments from one script to another
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have this code in a tool I am currently building:
while [ $# -gt 0 ]; do
case "$1" in
--var1=*)
var1="$1#*="
;;
--var2=*)
var1="$1#*="
;;
--var3=*)
var1="$1#*="
;;
*)
printf "***************************n
* Error: Invalid argument.*n
***************************n"
esac
shift
done
I have many options to add, but five of my options should be saved as arrays. So if I call the tool, let's say from the shell using something like this:./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"
How can I save the value of var1 as an array? Is that possible? And, if so, what is the best way to deal with these arrays in terms of efficiency if I have too many of them?.
bash shell shell-script
add a comment |
I have this code in a tool I am currently building:
while [ $# -gt 0 ]; do
case "$1" in
--var1=*)
var1="$1#*="
;;
--var2=*)
var1="$1#*="
;;
--var3=*)
var1="$1#*="
;;
*)
printf "***************************n
* Error: Invalid argument.*n
***************************n"
esac
shift
done
I have many options to add, but five of my options should be saved as arrays. So if I call the tool, let's say from the shell using something like this:./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"
How can I save the value of var1 as an array? Is that possible? And, if so, what is the best way to deal with these arrays in terms of efficiency if I have too many of them?.
bash shell shell-script
May be better to use getopts
– fedorqui
Oct 22 '15 at 10:53
2
@fedorqui,bash'sgetoptsdoesn't support long options. Onlyksh93's one does. See also thisgetopts_long
– Stéphane Chazelas
Oct 22 '15 at 11:05
is this what you need? : Specify command line arguments like name=value pairs for shell script
– JRichardsz
Mar 24 '17 at 20:36
add a comment |
I have this code in a tool I am currently building:
while [ $# -gt 0 ]; do
case "$1" in
--var1=*)
var1="$1#*="
;;
--var2=*)
var1="$1#*="
;;
--var3=*)
var1="$1#*="
;;
*)
printf "***************************n
* Error: Invalid argument.*n
***************************n"
esac
shift
done
I have many options to add, but five of my options should be saved as arrays. So if I call the tool, let's say from the shell using something like this:./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"
How can I save the value of var1 as an array? Is that possible? And, if so, what is the best way to deal with these arrays in terms of efficiency if I have too many of them?.
bash shell shell-script
I have this code in a tool I am currently building:
while [ $# -gt 0 ]; do
case "$1" in
--var1=*)
var1="$1#*="
;;
--var2=*)
var1="$1#*="
;;
--var3=*)
var1="$1#*="
;;
*)
printf "***************************n
* Error: Invalid argument.*n
***************************n"
esac
shift
done
I have many options to add, but five of my options should be saved as arrays. So if I call the tool, let's say from the shell using something like this:./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"
How can I save the value of var1 as an array? Is that possible? And, if so, what is the best way to deal with these arrays in terms of efficiency if I have too many of them?.
bash shell shell-script
bash shell shell-script
edited Oct 22 '15 at 12:32
Brian
1,0521412
1,0521412
asked Oct 22 '15 at 10:46
Ahmad alkaidAhmad alkaid
2516
2516
May be better to use getopts
– fedorqui
Oct 22 '15 at 10:53
2
@fedorqui,bash'sgetoptsdoesn't support long options. Onlyksh93's one does. See also thisgetopts_long
– Stéphane Chazelas
Oct 22 '15 at 11:05
is this what you need? : Specify command line arguments like name=value pairs for shell script
– JRichardsz
Mar 24 '17 at 20:36
add a comment |
May be better to use getopts
– fedorqui
Oct 22 '15 at 10:53
2
@fedorqui,bash'sgetoptsdoesn't support long options. Onlyksh93's one does. See also thisgetopts_long
– Stéphane Chazelas
Oct 22 '15 at 11:05
is this what you need? : Specify command line arguments like name=value pairs for shell script
– JRichardsz
Mar 24 '17 at 20:36
May be better to use getopts
– fedorqui
Oct 22 '15 at 10:53
May be better to use getopts
– fedorqui
Oct 22 '15 at 10:53
2
2
@fedorqui,
bash's getopts doesn't support long options. Only ksh93's one does. See also this getopts_long– Stéphane Chazelas
Oct 22 '15 at 11:05
@fedorqui,
bash's getopts doesn't support long options. Only ksh93's one does. See also this getopts_long– Stéphane Chazelas
Oct 22 '15 at 11:05
is this what you need? : Specify command line arguments like name=value pairs for shell script
– JRichardsz
Mar 24 '17 at 20:36
is this what you need? : Specify command line arguments like name=value pairs for shell script
– JRichardsz
Mar 24 '17 at 20:36
add a comment |
2 Answers
2
active
oldest
votes
If on Linux (with the util-linux utilities including getopt installed, or the one from busybox), you can do:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case "$opt_spec[$o]" in
(*'()') eval "$opt_spec[$o]%??+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
That way, you can call your script as:
my-script --opt1=foo --opt2 bar --opt4 -- whatever
And getopt will do the hard work of parsing it, handling -- and abbreviations for you.
Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec associative array definition:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$opt_spec[$o]+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
You can add short options like:
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="$!short_opt_spec[*]"
IFS=,
getopt -o "+$short_opts" -l "$!long_opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($long_opt_spec[$o]+1)); then # opt without argument
eval "$long_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$long_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$long_opt_spec[$o]+=("$1")";;
(*) eval "$long_opt_spec[$o]=$1"
esac
shift
fi;;
(-*)
o=$o#-
if (($short_opt_spec[$o]+1)); then # opt without argument
eval "$short_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$short_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$short_opt_spec[$o]+=("$1")";;
(*) eval "$short_opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
1
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
add a comment |
I would suggest you take a look at my General Shell Script GitHub: utility_functions.sh. There you will see a function called getArgs. It's designed for associating options and values.
I'm pasting here the function only, but it depends on a couple more functions inside that script
##########################
#
# Function name: getArgs
#
# Description:
# This function provides the getopts functionality
# while allowing the use of long operations and list of parameters.
# in the case of a list of arguments for only one option, this list
# will be returned as a single-space-separated list in one single string.
#
# Pre-reqs:
# None
#
# Output:
# GA_OPTION variable will hold the current option
# GA_VALUE variable will hold the value (or list of values) associated
# with the current option
#
# Usage:
# You have to source the function in order to be able to access the GA_OPTIONS
# and GA_VALUES variables
# . getArgs $*
#
####################
function getArgs grep "-")
# Looking for short (-) or long (--) options
isOption=$(expr index "$dash" "-")
# Initialize the counter
counter=0
# Loop while there are arguments left
while [[ $# -gt 0 ]]
do
if [[ $dash && $isOption -eq 1 ]]
then
(( counter+=1 ))
GA_OPTIONS[$counter]=$1
shift
else
if [[ -z $GA_VALUES[$counter] ]]
then
GA_VALUES[$counter]=$1
else
GA_VALUES[$counter]="$GA_VALUES[$counter] $1"
fi
shift
fi
dash=$(echo $1
As you see, this particular function will export GA_OPTIONS and GA_VALUES. Only condition for this is that the values must be a space-separated list after the option.
You would call the script as
./tool --var1 2 3 4 5 --var2="6" --var3="7"
Or just use similar logic to accommodate your preferences.
1
getArgs $*would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.
– Stéphane Chazelas
Oct 23 '15 at 6:36
echo $1 | grep -, Would return the lines in the output ofecho $1(again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.
– Stéphane Chazelas
Oct 23 '15 at 6:38
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f237877%2fpassing-named-arguments-as-array-in-shell-script%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
If on Linux (with the util-linux utilities including getopt installed, or the one from busybox), you can do:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case "$opt_spec[$o]" in
(*'()') eval "$opt_spec[$o]%??+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
That way, you can call your script as:
my-script --opt1=foo --opt2 bar --opt4 -- whatever
And getopt will do the hard work of parsing it, handling -- and abbreviations for you.
Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec associative array definition:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$opt_spec[$o]+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
You can add short options like:
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="$!short_opt_spec[*]"
IFS=,
getopt -o "+$short_opts" -l "$!long_opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($long_opt_spec[$o]+1)); then # opt without argument
eval "$long_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$long_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$long_opt_spec[$o]+=("$1")";;
(*) eval "$long_opt_spec[$o]=$1"
esac
shift
fi;;
(-*)
o=$o#-
if (($short_opt_spec[$o]+1)); then # opt without argument
eval "$short_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$short_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$short_opt_spec[$o]+=("$1")";;
(*) eval "$short_opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
1
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
add a comment |
If on Linux (with the util-linux utilities including getopt installed, or the one from busybox), you can do:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case "$opt_spec[$o]" in
(*'()') eval "$opt_spec[$o]%??+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
That way, you can call your script as:
my-script --opt1=foo --opt2 bar --opt4 -- whatever
And getopt will do the hard work of parsing it, handling -- and abbreviations for you.
Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec associative array definition:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$opt_spec[$o]+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
You can add short options like:
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="$!short_opt_spec[*]"
IFS=,
getopt -o "+$short_opts" -l "$!long_opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($long_opt_spec[$o]+1)); then # opt without argument
eval "$long_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$long_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$long_opt_spec[$o]+=("$1")";;
(*) eval "$long_opt_spec[$o]=$1"
esac
shift
fi;;
(-*)
o=$o#-
if (($short_opt_spec[$o]+1)); then # opt without argument
eval "$short_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$short_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$short_opt_spec[$o]+=("$1")";;
(*) eval "$short_opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
1
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
add a comment |
If on Linux (with the util-linux utilities including getopt installed, or the one from busybox), you can do:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case "$opt_spec[$o]" in
(*'()') eval "$opt_spec[$o]%??+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
That way, you can call your script as:
my-script --opt1=foo --opt2 bar --opt4 -- whatever
And getopt will do the hard work of parsing it, handling -- and abbreviations for you.
Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec associative array definition:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$opt_spec[$o]+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
You can add short options like:
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="$!short_opt_spec[*]"
IFS=,
getopt -o "+$short_opts" -l "$!long_opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($long_opt_spec[$o]+1)); then # opt without argument
eval "$long_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$long_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$long_opt_spec[$o]+=("$1")";;
(*) eval "$long_opt_spec[$o]=$1"
esac
shift
fi;;
(-*)
o=$o#-
if (($short_opt_spec[$o]+1)); then # opt without argument
eval "$short_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$short_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$short_opt_spec[$o]+=("$1")";;
(*) eval "$short_opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
If on Linux (with the util-linux utilities including getopt installed, or the one from busybox), you can do:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case "$opt_spec[$o]" in
(*'()') eval "$opt_spec[$o]%??+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
That way, you can call your script as:
my-script --opt1=foo --opt2 bar --opt4 -- whatever
And getopt will do the hard work of parsing it, handling -- and abbreviations for you.
Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec associative array definition:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "$!opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($opt_spec[$o]+1)); then # opt without argument
eval "$opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$opt_spec[$o]+=("$1")";;
(*) eval "$opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
You can add short options like:
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="$!short_opt_spec[*]"
IFS=,
getopt -o "+$short_opts" -l "$!long_opt_spec[*]" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=$o#--
if (($long_opt_spec[$o]+1)); then # opt without argument
eval "$long_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$long_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$long_opt_spec[$o]+=("$1")";;
(*) eval "$long_opt_spec[$o]=$1"
esac
shift
fi;;
(-*)
o=$o#-
if (($short_opt_spec[$o]+1)); then # opt without argument
eval "$short_opt_spec[$o]=true"
else
o=$o:
case $(declare -p "$short_opt_spec[$o]" 2> /dev/null) in
("declare -a"*) eval "$short_opt_spec[$o]+=("$1")";;
(*) eval "$short_opt_spec[$o]=$1"
esac
shift
fi
esac
done
echo "var1: $var1[@]"
edited Mar 18 '16 at 9:08
Community♦
1
1
answered Oct 22 '15 at 11:20
Stéphane ChazelasStéphane Chazelas
315k57597955
315k57597955
1
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
add a comment |
1
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
1
1
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
Hi @Stéphane , thanks for your effort. Really amazing :)
– Ahmad alkaid
Oct 22 '15 at 14:50
add a comment |
I would suggest you take a look at my General Shell Script GitHub: utility_functions.sh. There you will see a function called getArgs. It's designed for associating options and values.
I'm pasting here the function only, but it depends on a couple more functions inside that script
##########################
#
# Function name: getArgs
#
# Description:
# This function provides the getopts functionality
# while allowing the use of long operations and list of parameters.
# in the case of a list of arguments for only one option, this list
# will be returned as a single-space-separated list in one single string.
#
# Pre-reqs:
# None
#
# Output:
# GA_OPTION variable will hold the current option
# GA_VALUE variable will hold the value (or list of values) associated
# with the current option
#
# Usage:
# You have to source the function in order to be able to access the GA_OPTIONS
# and GA_VALUES variables
# . getArgs $*
#
####################
function getArgs grep "-")
# Looking for short (-) or long (--) options
isOption=$(expr index "$dash" "-")
# Initialize the counter
counter=0
# Loop while there are arguments left
while [[ $# -gt 0 ]]
do
if [[ $dash && $isOption -eq 1 ]]
then
(( counter+=1 ))
GA_OPTIONS[$counter]=$1
shift
else
if [[ -z $GA_VALUES[$counter] ]]
then
GA_VALUES[$counter]=$1
else
GA_VALUES[$counter]="$GA_VALUES[$counter] $1"
fi
shift
fi
dash=$(echo $1
As you see, this particular function will export GA_OPTIONS and GA_VALUES. Only condition for this is that the values must be a space-separated list after the option.
You would call the script as
./tool --var1 2 3 4 5 --var2="6" --var3="7"
Or just use similar logic to accommodate your preferences.
1
getArgs $*would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.
– Stéphane Chazelas
Oct 23 '15 at 6:36
echo $1 | grep -, Would return the lines in the output ofecho $1(again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.
– Stéphane Chazelas
Oct 23 '15 at 6:38
add a comment |
I would suggest you take a look at my General Shell Script GitHub: utility_functions.sh. There you will see a function called getArgs. It's designed for associating options and values.
I'm pasting here the function only, but it depends on a couple more functions inside that script
##########################
#
# Function name: getArgs
#
# Description:
# This function provides the getopts functionality
# while allowing the use of long operations and list of parameters.
# in the case of a list of arguments for only one option, this list
# will be returned as a single-space-separated list in one single string.
#
# Pre-reqs:
# None
#
# Output:
# GA_OPTION variable will hold the current option
# GA_VALUE variable will hold the value (or list of values) associated
# with the current option
#
# Usage:
# You have to source the function in order to be able to access the GA_OPTIONS
# and GA_VALUES variables
# . getArgs $*
#
####################
function getArgs grep "-")
# Looking for short (-) or long (--) options
isOption=$(expr index "$dash" "-")
# Initialize the counter
counter=0
# Loop while there are arguments left
while [[ $# -gt 0 ]]
do
if [[ $dash && $isOption -eq 1 ]]
then
(( counter+=1 ))
GA_OPTIONS[$counter]=$1
shift
else
if [[ -z $GA_VALUES[$counter] ]]
then
GA_VALUES[$counter]=$1
else
GA_VALUES[$counter]="$GA_VALUES[$counter] $1"
fi
shift
fi
dash=$(echo $1
As you see, this particular function will export GA_OPTIONS and GA_VALUES. Only condition for this is that the values must be a space-separated list after the option.
You would call the script as
./tool --var1 2 3 4 5 --var2="6" --var3="7"
Or just use similar logic to accommodate your preferences.
1
getArgs $*would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.
– Stéphane Chazelas
Oct 23 '15 at 6:36
echo $1 | grep -, Would return the lines in the output ofecho $1(again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.
– Stéphane Chazelas
Oct 23 '15 at 6:38
add a comment |
I would suggest you take a look at my General Shell Script GitHub: utility_functions.sh. There you will see a function called getArgs. It's designed for associating options and values.
I'm pasting here the function only, but it depends on a couple more functions inside that script
##########################
#
# Function name: getArgs
#
# Description:
# This function provides the getopts functionality
# while allowing the use of long operations and list of parameters.
# in the case of a list of arguments for only one option, this list
# will be returned as a single-space-separated list in one single string.
#
# Pre-reqs:
# None
#
# Output:
# GA_OPTION variable will hold the current option
# GA_VALUE variable will hold the value (or list of values) associated
# with the current option
#
# Usage:
# You have to source the function in order to be able to access the GA_OPTIONS
# and GA_VALUES variables
# . getArgs $*
#
####################
function getArgs grep "-")
# Looking for short (-) or long (--) options
isOption=$(expr index "$dash" "-")
# Initialize the counter
counter=0
# Loop while there are arguments left
while [[ $# -gt 0 ]]
do
if [[ $dash && $isOption -eq 1 ]]
then
(( counter+=1 ))
GA_OPTIONS[$counter]=$1
shift
else
if [[ -z $GA_VALUES[$counter] ]]
then
GA_VALUES[$counter]=$1
else
GA_VALUES[$counter]="$GA_VALUES[$counter] $1"
fi
shift
fi
dash=$(echo $1
As you see, this particular function will export GA_OPTIONS and GA_VALUES. Only condition for this is that the values must be a space-separated list after the option.
You would call the script as
./tool --var1 2 3 4 5 --var2="6" --var3="7"
Or just use similar logic to accommodate your preferences.
I would suggest you take a look at my General Shell Script GitHub: utility_functions.sh. There you will see a function called getArgs. It's designed for associating options and values.
I'm pasting here the function only, but it depends on a couple more functions inside that script
##########################
#
# Function name: getArgs
#
# Description:
# This function provides the getopts functionality
# while allowing the use of long operations and list of parameters.
# in the case of a list of arguments for only one option, this list
# will be returned as a single-space-separated list in one single string.
#
# Pre-reqs:
# None
#
# Output:
# GA_OPTION variable will hold the current option
# GA_VALUE variable will hold the value (or list of values) associated
# with the current option
#
# Usage:
# You have to source the function in order to be able to access the GA_OPTIONS
# and GA_VALUES variables
# . getArgs $*
#
####################
function getArgs grep "-")
# Looking for short (-) or long (--) options
isOption=$(expr index "$dash" "-")
# Initialize the counter
counter=0
# Loop while there are arguments left
while [[ $# -gt 0 ]]
do
if [[ $dash && $isOption -eq 1 ]]
then
(( counter+=1 ))
GA_OPTIONS[$counter]=$1
shift
else
if [[ -z $GA_VALUES[$counter] ]]
then
GA_VALUES[$counter]=$1
else
GA_VALUES[$counter]="$GA_VALUES[$counter] $1"
fi
shift
fi
dash=$(echo $1
As you see, this particular function will export GA_OPTIONS and GA_VALUES. Only condition for this is that the values must be a space-separated list after the option.
You would call the script as
./tool --var1 2 3 4 5 --var2="6" --var3="7"
Or just use similar logic to accommodate your preferences.
edited 8 hours ago
Rui F Ribeiro
42.1k1484142
42.1k1484142
answered Oct 23 '15 at 5:58
Jesus A. SanchezJesus A. Sanchez
42425
42425
1
getArgs $*would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.
– Stéphane Chazelas
Oct 23 '15 at 6:36
echo $1 | grep -, Would return the lines in the output ofecho $1(again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.
– Stéphane Chazelas
Oct 23 '15 at 6:38
add a comment |
1
getArgs $*would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.
– Stéphane Chazelas
Oct 23 '15 at 6:36
echo $1 | grep -, Would return the lines in the output ofecho $1(again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.
– Stéphane Chazelas
Oct 23 '15 at 6:38
1
1
getArgs $* would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.– Stéphane Chazelas
Oct 23 '15 at 6:36
getArgs $* would pass the result of the split+glob operator applied to the list of positional parameters to getArgs, it doesn't make any sense.– Stéphane Chazelas
Oct 23 '15 at 6:36
echo $1 | grep -, Would return the lines in the output of echo $1 (again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.– Stéphane Chazelas
Oct 23 '15 at 6:38
echo $1 | grep -, Would return the lines in the output of echo $1 (again $1 being subject to split+glob, and echo expanding sequences) that contain a dash.– Stéphane Chazelas
Oct 23 '15 at 6:38
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f237877%2fpassing-named-arguments-as-array-in-shell-script%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
-bash, shell, shell-script
May be better to use getopts
– fedorqui
Oct 22 '15 at 10:53
2
@fedorqui,
bash'sgetoptsdoesn't support long options. Onlyksh93's one does. See also thisgetopts_long– Stéphane Chazelas
Oct 22 '15 at 11:05
is this what you need? : Specify command line arguments like name=value pairs for shell script
– JRichardsz
Mar 24 '17 at 20:36