ChatGPT解决这个技术问题 Extra ChatGPT

Convert command line arguments into an array in Bash

How do I convert command-line arguments into a bash script array?

I want to take this:

./something.sh arg1 arg2 arg3

and convert it to

myArray=( arg1 arg2 arg3 )

so that I can use myArray for further use in the script.

This previous SO post comes close, but doesn't go into how to create an array: How do I parse command line arguments in Bash?

I need to convert the arguments into a regular bash script array; I realize I could use other languages (Python, for instance) but need to do this in bash. I guess I'm looking for an "append" function or something similar?

UPDATE: I also wanted to ask how to check for zero arguments and assign a default array value, and thanks to the answer below, was able to get this working:

if [ "$#" -eq 0 ]; then
  myArray=( defaultarg1 defaultarg2 )
else
  myArray=( "$@" )
fi

k
kojiro

Actually your command line arguments are practically like an array already. At least, you can treat the $@ variable much like an array. That said, you can convert it into an actual array like this:

myArray=( "$@" )

If you just want to type some arguments and feed them into the $@ value, use set:

$ set -- apple banana "kiwi fruit"
$ echo "$#"
3
$ echo "$@"
apple banana kiwi fruit

Understanding how to use the argument structure is particularly useful in POSIX sh, which has nothing else like an array.


Thanks! Works great! Was just about to ask how to check for zero arguments and assign a default array value, and the $# works perfectly for that!
set allows you to set positional parameters for the scope. It also lets you set shell options. You can do set foo, which will mean $1 expands to "foo", but if your parameters start with a dash set will assume you mean to set a shell option. The double-dash ensures that all the following parameters are interpreted as positional parameters to be set.
One gotcha: echo $@ will print all the arguments, but echo $myArray will only print the first element. To see them all, use echo ${myArray[@]}.
@z0r If you don't put double quotes around those expansions then bash will re-wordsplit them, and possibly lose meaning.
Right, the general way to "splat" an array and use each element is "${myArray[@]}". If you want to loop through the array, you need the quotes to avoid splitting its individual elements on IFS
N
Nahuel Fouilleul

Maybe this can help:

myArray=("$@") 

also you can iterate over arguments by omitting 'in':

for arg; do
   echo "$arg"
done

will be equivalent

for arg in "${myArray[@]}"; do
   echo "$arg"
done

Newbie questions: How does bash know what to put into the arg field - is it a predefined variable? ${var} is expanded to the content of var. ${var[n]} is expanded to the content of element n of array var. Is ${var[@]} then expanding the entire array, i.e. ${var[0]} ${var[1]} ... ${var[n]} (with nbeing the last element's index)?
[for] without [in] will loop over arguments array $@ ($1,$2, etc.). Which can be set also with [set] command, for example set -- arg1 arg2
Y
Yaron

Actually the list of parameters could be accessed with $1 $2 ... etc.
Which is exactly equivalent to:

${!i}

So, the list of parameters could be changed with set,
and ${!i} is the correct way to access them:

$ set -- aa bb cc dd 55 ff gg hh ii jjj kkk lll
$ for ((i=0;i<=$#;i++)); do echo "$#" "$i" "${!i}"; done
12 1 aa
12 2 bb
12 3 cc
12 4 dd
12 5 55
12 6 ff
12 7 gg
12 8 hh
12 9 ii
12 10 jjj
12 11 kkk
12 12 lll

For your specific case, this could be used (without the need for arrays), to set the list of arguments when none was given:

if [ "$#" -eq 0 ]; then
    set -- defaultarg1 defaultarg2
fi

which translates to this even simpler expression:

[ "$#" == "0" ] && set -- defaultarg1 defaultarg2

Shouldn't the echo example be: echo "$#" "$i+1" "${!i}"; to get the output exactly as shown?
k
kittydoor

Here is another usage :

#!/bin/bash
array=( "$@" )
arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   echo "${array[$i]}"
done

Y
Yaron

Easier Yet, you can operate directly on $@ ;)

Here is how to do pass a a list of args directly from the prompt:

function echoarg { for stuff in "$@" ; do echo $stuff ; done ; } 
    echoarg Hey Ho Lets Go
    Hey
    Ho
    Lets
    Go

Even easier, for stuff in "$@" ; do ... is same as for stuff ; do ... :)
J
Jacob Wegelin

The importance of the double quotes is worth emphasizing. Suppose an argument contains whitespace.

Code:

#!/bin/bash
printf 'arguments:%s\n' "$@"
declare -a arrayGOOD=( "$@" )
declare -a arrayBAAD=(  $@  )

printf '\n%s:\n' arrayGOOD
declare -p arrayGOOD
arrayGOODlength=${#arrayGOOD[@]}
for (( i=1; i<${arrayGOODlength}+1; i++ ));
do
   echo "${arrayGOOD[$i-1]}"
done

printf '\n%s:\n' arrayBAAD
declare -p arrayBAAD
arrayBAADlength=${#arrayBAAD[@]}
for (( i=1; i<${arrayBAADlength}+1; i++ ));
do
   echo "${arrayBAAD[$i-1]}"
done

Output:

> ./bash-array-practice.sh 'The dog ate the "flea" -- and ' the mouse.
arguments:The dog ate the "flea" -- and 
arguments:the
arguments:mouse.

arrayGOOD:
declare -a arrayGOOD='([0]="The dog ate the \"flea\" -- and " [1]="the" [2]="mouse.")'
The dog ate the "flea" -- and 
the
mouse.

arrayBAAD:
declare -a arrayBAAD='([0]="The" [1]="dog" [2]="ate" [3]="the" [4]="\"flea\"" [5]="--" [6]="and" [7]="the" [8]="mouse.")'
The
dog
ate
the
"flea"
--
and
the
mouse.
> 

K
Kirin

Side-by-side view of how the array and $@ are practically the same.

Code:

#!/bin/bash

echo "Dollar-1 : $1"
echo "Dollar-2 : $2"
echo "Dollar-3 : $3"
echo "Dollar-AT: $@"
echo ""

myArray=( "$@" )

echo "A Val 0: ${myArray[0]}"
echo "A Val 1: ${myArray[1]}"
echo "A Val 2: ${myArray[2]}"
echo "A All Values: ${myArray[@]}"

Input:

./bash-array-practice.sh 1 2 3 4

Output:

Dollar-1 : 1
Dollar-2 : 2
Dollar-3 : 3
Dollar-AT: 1 2 3 4

A Val 0: 1
A Val 1: 2
A Val 2: 3
A All Values: 1 2 3 4