108

How do I create an array in Unix shell scripting?

3
  • 3
    See: Arrays in Unix Bourne Shell Commented Aug 24, 2016 at 20:06
  • 1
    in shell not without a little of accessors, in bash yes Commented Jul 3, 2024 at 13:29
  • To clarify the above comment, the issue with the question is that there is no such thing as "Unix shell [scripting]". Instead, there are multiple shells, with a POSIX-compatible one being kind-of the default, but Bash being another very popular option. What you can and can't do and how depends on the actual shell in use. Commented Feb 21 at 10:57

15 Answers 15

111

The following code creates and prints an array of strings in shell:

#!/bin/bash
array=("A" "B" "ElementC" "ElementE")
for element in "${array[@]}"
do
    echo "$element"
done

echo
echo "Number of elements: ${#array[@]}"
echo
echo "${array[@]}"

Result:

A
B
ElementC
ElementE

Number of elements: 4

A B ElementC ElementE
Sign up to request clarification or add additional context in comments.

1 Comment

In case you are wondering, @ means all elements of the array. See here for more.
64

In bash, you create array like this

arr=(one two three)

To access the elements

$ echo "${arr[0]}"
one
$ echo "${arr[2]}"
three

To ask for user input, you can use read

read -p "Enter your choice: " choice

3 Comments

The space-separated declaration does NOT work with /bin/sh throwing an error line 1: syntax error: unexpected "(". Do you know of an alternative?
Instread of /bin/sh, using /bin/bash will be ok. It seems that some features /bin/sh doesn't support, which is linked to /bin/dash, a lightweight interpreter.
/bin/sh is usually linked to some POSIX compatible shell. You can't assume Bash-specific features to work there. If you want Bash features, use Bash.
28

Bourne shell doesn't support arrays. However, there are two ways to handle the issue.

Use positional shell parameters $1, $2, etc.:

$ set one two three
$ echo $*
one two three
$ echo $#
3
$ echo $2
two

Use variable evaluations:

$ n=1 ; eval a$n="one" 
$ n=2 ; eval a$n="two" 
$ n=3 ; eval a$n="three"
$ n=2
$ eval echo \$a$n
two

5 Comments

Bash supports arrays. Not sure about original Bourne shell, but bash is more prevalent these days...
@zplesivcak - ... on GNU/Linux, since it's a GNU thing. For example, FreeBSD doesn't ship with bash (it's installable from ports though). Scripts written assuming bash features aren't portable, and they're noticably slower slower than most Bourne shell implementations (like dash, which is common on GNU/Linux distributions). bash is a nice interactive shell, but it's slow for scripting.
$* is considered harmful. Normally, $@ is preferred since it does the same, but keeps spaces. $@ is expanded as "$1" "$2" "$3" ... "$n", while $* is expanded as "$1x$2x$3x...$n", where x is $IFS separator (most likely, space).
Unquoted, $@ is the same as $*; the difference only shows up when quoted: "$*" is one word, while "$@" preserves the original word breaks.
The question is tagged bash, so bash-specific responses are appropriate, but it's certainly true that one shouldn't assume that /bin/sh is bash.
16

Your question asks about "unix shell scripting", but is tagged bash. Those are two different answers.

The POSIX specification for shells does not have anything to say about arrays, as the original Bourne shell did not support them. Even today, on FreeBSD, Ubuntu Linux, and many other systems, /bin/sh does not have array support. So if you want your script to work in different Bourne-compatible shells, you shouldn't use them. Alternatively, if you are assuming a specific shell, then be sure to put its full name in the shebang line, e.g. #!/usr/bin/env bash.

If you are using bash, zsh, or a modern version of ksh, you can create an array like this:

myArray=(first "second element" 3rd)

and access elements like this

$ echo "${myArray[1]}"
second element

You can get all the elements via "${myArray[@]}".

You can use the slice notation ${array[@]:skip:length} to restrict the portion of the array referenced, e.g. "${myArray[@]:1}" expands to all of the elements except the first one, while "${myArray[@]::3}" expands to the last three elements of the array.

The length of the array is ${#myArray[@]}.

You can generate an array of the valid indexes of an array with ${!myArray[@]}.

Older versions of ksh before ksh93 also had arrays, but not the parenthesis-based notation, nor did they support slicing or index extraction. You could create an array like this, though:

set -A myArray -- first "second element" 3rd 

Most of the above is also true in Zsh, but there are some differences:

  • Array indexes start at 1 rather than 0 by default
  • Despite the basis difference, the values in the slice syntax are the same – the first value is the number of elements to skip rather than the index of the first item to include
  • Zsh also has its own native slice notation, which is the index of the start and end elements joined by a comma within the subscript brackets: the equivalent of "${myArray[@]:1}" is $myArray[2,-1] and the equivalent of "${myArray[@]::3}" is $myArray[-3,-1]
  • When using subscripted array references with nothing after the close bracket, the curly braces are not needed.
  • The brackets themselves are not needed for the element count; $#array works
  • Similarly, $array expands to the full array rather than just the first element; it's almost the same as "${array[@]}", except that any elements equal to the empty string are omitted
  • Bash and Ksh support sparse arrays; you can store elements at any index without populating the slots in between, and ${#array[@]} is always the number of elements actually present. Zsh doesn't have this support; $#array is always the highest index in use. So while ${!array[@]} doesn't work in Zsh, it would always produce the same result as {1..$#array} anyway. (Older ksh versions without ${!array[@]} did nonetheless support sparse arrays; you would have to manually loop through index values to determine which ones corresponded to an element.)

Comments

13
#!/bin/bash

# define a array, space to separate every item
foo=(foo1 foo2)

# access
echo "${foo[1]}"

# add or changes
foo[0]=bar
foo[2]=cat
foo[1000]=also_OK

You can read the ABS "Advanced Bash-Scripting Guide"

3 Comments

Please reconsider suggesting the ABS as a learning resource -- it's in many ways to bash what W3Schools is to HTML and Javascript, having lots of Google juice but showcasing bad practices in many of its examples, and rarely and inadequately updated. The bash-hackers' wiki is a much better resource; so is the BashGuide.
The space-separated declaration does NOT work with /bin/sh throwing an error line 1: syntax error: unexpected "(". Do you know of an alternative?
@mhyousefi your /bin/sh is probably a shell that doesn't support arrays.
9

The Bourne shell and C shell don't have arrays, IIRC.

In addition to what others have said, in Bash you can get the number of elements in an array as follows:

elements=${#arrayname[@]}

and do slice-style operations:

arrayname=(apple banana cherry)
echo ${arrayname[@]:1}                   # yields "banana cherry"
echo ${arrayname[@]: -1}                 # yields "cherry"
echo ${arrayname[${#arrayname[@]}-1]}    # yields "cherry"
echo ${arrayname[@]:0:2}                 # yields "apple banana"
echo ${arrayname[@]:1:1}                 # yields "banana"

3 Comments

csh does have arrays.
@KeithThompson: It's not documented in the man page but the functionality does appear to be present in at least some versions.
The man page doesn't mention "arrays" by that name, but see the documentation of the set command (set name=(wordlist)) and the "Variable substituion" section ($name[selector] and ${name[selector]}). As far as I know, csh has always supported arrays. See, for example, the $path array variable, which mirrors the $PATH environment variable.
8

Try this :

echo "Find the Largest Number and Smallest Number of a given number"
echo "---------------------------------------------------------------------------------"
echo "Enter the number"
read n
i=0

while [ $n -gt 0 ] #For Seperating digits and Stored into array "x"
do
        x[$i]=`expr $n % 10`
        n=`expr $n / 10`
        i=`expr $i + 1`
done

echo "Array values ${x[@]}"  # For displaying array elements


len=${#x[*]}  # it returns the array length


for (( i=0; i<len; i++ ))    # For Sorting array elements using Bubble sort
do
    for (( j=i+1; j<len;  j++ ))
    do
        if [ `echo "${x[$i]} > ${x[$j]}"|bc` ]
        then
                t=${x[$i]}
                t=${x[$i]}
                x[$i]=${x[$j]}
                x[$j]=$t
        fi
        done
done


echo "Array values ${x[*]}"  # Displaying of Sorted Array


for (( i=len-1; i>=0; i-- ))  # Form largest number
do
   a=`echo $a \* 10 + ${x[$i]}|bc`
done

echo "Largest Number is : $a"

l=$a  #Largest number

s=0
while [ $a -gt 0 ]  # Reversing of number, We get Smallest number
do
        r=`expr $a % 10`
        s=`echo "$s * 10 + $r"|bc`
        a=`expr $a / 10`
done
echo "Smallest Number is : $s" #Smallest Number

echo "Difference between Largest number and Smallest number"
echo "=========================================="
Diff=`expr $l - $s`
echo "Result is : $Diff"


echo "If you try it, We can get it"

Comments

5

You can try of the following type :

#!/bin/bash
 declare -a arr

 i=0
 j=0

  for dir in $(find /home/rmajeti/programs -type d)
   do
        arr[i]=$dir
        i=$((i+1))
   done


  while [ $j -lt $i ]
  do
        echo ${arr[$j]}
        j=$((j+1))
  done

1 Comment

breaks on directory names with spaces. use a while read loop of change IFS to take care of that.
5

An array can be loaded in twoways.

set -A TEST_ARRAY alpha beta gamma

or

X=0 # Initialize counter to zero.

-- Load the array with the strings alpha, beta, and gamma

for ELEMENT in alpha gamma beta
do
    TEST_ARRAY[$X]=$ELEMENT
    ((X = X + 1))
done

Also, I think below information may help:

The shell supports one-dimensional arrays. The maximum number of array elements is 1,024. When an array is defined, it is automatically dimensioned to 1,024 elements. A one-dimensional array contains a sequence of array elements, which are like the boxcars connected together on a train track.

In case you want to access the array:

echo ${MY_ARRAY[2] # Show the third array element
 gamma 


echo ${MY_ARRAY[*] # Show all array elements
-   alpha beta gamma


echo ${MY_ARRAY[@] # Show all array elements
 -  alpha beta gamma


echo ${#MY_ARRAY[*]} # Show the total number of array elements
-   3


echo ${#MY_ARRAY[@]} # Show the total number of array elements
-   3

echo ${MY_ARRAY} # Show array element 0 (the first element)
-  alpha

Comments

4

If you want a key value store with support for spaces use the -A parameter:

declare -A programCollection
programCollection["xwininfo"]="to aquire information about the target window."

for program in ${!programCollection[@]}
do
    echo "The program ${program} is used ${programCollection[${program}]}"
done

http://linux.die.net/man/1/bash "Associative arrays are created using declare -A name. "

Comments

4

There are multiple ways to create an array in shell.

ARR[0]="ABC"
ARR[1]="BCD"
echo ${ARR[*]}

${ARR[*]} prints all elements in the array.

Second way is:

ARR=("A" "B" "C" "D" 5 7 "J")
echo ${#ARR[@]}
echo ${ARR[0]}

${#ARR[@]} is used to count length of the array.

1 Comment

Nice answer, Great start for a newbie. And welcome to upvote levels ;-)
3

To read the values from keybord and insert element into array

# enter 0 when exit the insert element
echo "Enter the numbers"
read n
while [ $n -ne 0 ]
do
    x[$i]=`expr $n`
    read n
    let i++
done

#display the all array elements
echo "Array values ${x[@]}"
echo "Array values ${x[*]}"

# To find the array length
length=${#x[*]}
echo $length

Comments

3

A Simple way :

arr=("sharlock"  "bomkesh"  "feluda" )  ##declare array

len=${#arr[*]}  #determine length of array

# iterate with for loop
for (( i=0; i<len; i++ ))
do
    echo ${arr[$i]}
done

1 Comment

bash, zsh, or sh?
2

sh can parse between spaces. It looks like an array to me.

#!/bin/sh
list="A B C"

for elem in $list ; do
    echo $elem
done

Comments

1

In ksh you do it:

set -A array element1 element2 elementn

# view the first element
echo ${array[0]}

# Amount elements (You have to substitute 1)
echo ${#array[*]}

# show last element
echo ${array[ $(( ${#array[*]} - 1 )) ]}

1 Comment

A more concise way to show the last element is echo "${array[@]:(-1)}". This eliminates the need to write the array variable name twice.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.