Arrays in Unix Bourne Shell

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
23
down vote

favorite
10












I am trying to use arrays in Bourne shell (/bin/sh). I found that the way to initialize array elements is:



arr=(1 2 3)


But it is encountering an error:



syntax error at line 8: `arr=' unexpected


Now the post where I found this syntax says it is for bash, but I could not find any separate syntax for Bourne shell. Does the syntax stand the same for /bin/sh as well?










share|improve this question























  • check this question stackoverflow.com/questions/9481702/… on stack overflow
    – Nischay
    Jun 17 '14 at 9:41






  • 1




    Thnx @Nischay...After reading the link you provided, I refined my query string in google and got the link -docstore.mik.ua/orelly/unix/upt/ch45_34.htm
    – SubhasisM
    Jun 17 '14 at 10:07















up vote
23
down vote

favorite
10












I am trying to use arrays in Bourne shell (/bin/sh). I found that the way to initialize array elements is:



arr=(1 2 3)


But it is encountering an error:



syntax error at line 8: `arr=' unexpected


Now the post where I found this syntax says it is for bash, but I could not find any separate syntax for Bourne shell. Does the syntax stand the same for /bin/sh as well?










share|improve this question























  • check this question stackoverflow.com/questions/9481702/… on stack overflow
    – Nischay
    Jun 17 '14 at 9:41






  • 1




    Thnx @Nischay...After reading the link you provided, I refined my query string in google and got the link -docstore.mik.ua/orelly/unix/upt/ch45_34.htm
    – SubhasisM
    Jun 17 '14 at 10:07













up vote
23
down vote

favorite
10









up vote
23
down vote

favorite
10






10





I am trying to use arrays in Bourne shell (/bin/sh). I found that the way to initialize array elements is:



arr=(1 2 3)


But it is encountering an error:



syntax error at line 8: `arr=' unexpected


Now the post where I found this syntax says it is for bash, but I could not find any separate syntax for Bourne shell. Does the syntax stand the same for /bin/sh as well?










share|improve this question















I am trying to use arrays in Bourne shell (/bin/sh). I found that the way to initialize array elements is:



arr=(1 2 3)


But it is encountering an error:



syntax error at line 8: `arr=' unexpected


Now the post where I found this syntax says it is for bash, but I could not find any separate syntax for Bourne shell. Does the syntax stand the same for /bin/sh as well?







shell array bourne-shell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 13 '15 at 14:47









dhag

10.8k32742




10.8k32742










asked Jun 17 '14 at 9:40









SubhasisM

118116




118116











  • check this question stackoverflow.com/questions/9481702/… on stack overflow
    – Nischay
    Jun 17 '14 at 9:41






  • 1




    Thnx @Nischay...After reading the link you provided, I refined my query string in google and got the link -docstore.mik.ua/orelly/unix/upt/ch45_34.htm
    – SubhasisM
    Jun 17 '14 at 10:07

















  • check this question stackoverflow.com/questions/9481702/… on stack overflow
    – Nischay
    Jun 17 '14 at 9:41






  • 1




    Thnx @Nischay...After reading the link you provided, I refined my query string in google and got the link -docstore.mik.ua/orelly/unix/upt/ch45_34.htm
    – SubhasisM
    Jun 17 '14 at 10:07
















check this question stackoverflow.com/questions/9481702/… on stack overflow
– Nischay
Jun 17 '14 at 9:41




check this question stackoverflow.com/questions/9481702/… on stack overflow
– Nischay
Jun 17 '14 at 9:41




1




1




Thnx @Nischay...After reading the link you provided, I refined my query string in google and got the link -docstore.mik.ua/orelly/unix/upt/ch45_34.htm
– SubhasisM
Jun 17 '14 at 10:07





Thnx @Nischay...After reading the link you provided, I refined my query string in google and got the link -docstore.mik.ua/orelly/unix/upt/ch45_34.htm
– SubhasisM
Jun 17 '14 at 10:07











4 Answers
4






active

oldest

votes

















up vote
41
down vote



accepted










/bin/sh is hardly ever a Bourne shell on any systems nowadays (even Solaris which was one of the last major system to include it has now switched to a POSIX sh for its /bin/sh in Solaris 11). /bin/sh was the Thompson shell in the early 70s. The Bourne shell replaced it in Unix V7 in 1979.



/bin/sh has been the Bourne shell for many years thereafter (or the Almquist shell, a free reimplementation on BSDs).



Nowadays, /bin/sh is more commonly an interpreter or another for the POSIX sh language which is itself based on a subset of the language of ksh88 (and a superset of the Bourne shell language with some incompatibilities).



The Bourne shell or the POSIX sh language specification don't support arrays. Or rather they have only one array: the positional parameters ($1, $2, $@, so one array per function as well).



ksh88 did have arrays which you set with set -A, but that didn't get specified in the POSIX sh as the syntax is awkward and not very usable.



Other shells with array/lists variables include: csh/tcsh, rc, es, bash (which mostly copied the ksh syntax the ksh93 way), yash, zsh, fish each with a different syntax (rc the shell of the once to-be successor of Unix, fish and zsh being the most consistent ones)...



In standard sh (also works in modern versions of the Bourne shell):



set '1st element' 2 3 # setting the array

set -- "$@" more # adding elements to the end of the array

shift 2 # removing elements (here 2) from the beginning of the array

printf '<%s>n' "$@" # passing all the elements of the $@ array
# as arguments to a command

for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"n' "$i"
done

printf '%sn' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "$10") past the 9th in other
# shells.

printf '%sn' "$# elements in the array"

printf '%sn' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)


(note that in the Bourne shell and ksh88, $IFS must contain the space character for "$@" to work properly (a bug), and in the Bourne shell, you can't access elements above $9 ($10 won't work, you can still do shift 1; echo "$9" or loop over them)).






share|improve this answer


















  • 2




    Thanks a ton...your detailed explanation was very helpful.
    – SubhasisM
    Jun 17 '14 at 10:21







  • 1




    It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
    – kojiro
    Jan 22 '16 at 16:37











  • @kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
    – Stéphane Chazelas
    Oct 23 '17 at 6:57


















up vote
3
down vote













There are no arrays in plain Bourne shell. You can use the following way to create an array and traverse it:



#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell

array_traverse()

for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo $$current_value)
done
return 1


ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3


No matter what way to use arrays in sh would you pick it will always be cumbersome. Consider using a different language such as Python or Perl if you can unless you are stuck with a very limited platform or want to learn something.






share|improve this answer






















  • Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
    – SubhasisM
    Jun 17 '14 at 10:51











  • @NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
    – Stéphane Chazelas
    Jun 17 '14 at 11:42











  • POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
    – Arkadiusz Drabczyk
    Jun 17 '14 at 12:17










  • @Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
    – SubhasisM
    Jun 17 '14 at 13:42







  • 2




    Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
    – Stéphane Chazelas
    Jun 17 '14 at 13:51

















up vote
2
down vote













As the others have said, the Bourne Shell doesn't have true arrays.



However, depending on what you need to do, delimited strings should suffice:



sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%sn' "$word"
done


If the typical delimiters (space, tab, and newline) don't suffice, you can set IFS to whatever delimiter you want before the loop.



And if you need to build the array programmatically, you can just build up a delimited string.






share|improve this answer


















  • 1




    Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
    – Stéphane Chazelas
    May 13 '15 at 14:55

















up vote
0
down vote













A way to simulate arrays in dash (it can be adapted for any number of dimensions of an array):
(Please note that the use of the seq command requires that IFS is set to ' ' (SPACE = the default value). You can use while ... do ... or do ... while ... loops instead to avoid this (i kept seq in the scope of a better illustration of what the code does).)



#!/bin/sh

## The following functions implement vectors (arrays) operations in dash:
## Definition of a vector <v>:
## v_0 - variable that stores the number of elements of the vector
## v_1..v_n, where n=v_0 - variables that store the values of the vector elements

VectorAddElementNext ()
# Vector Add Element Next
# Adds the string contained in variable $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElementDVNext ()
# Vector Add Element Direct Value Next
# Adds the string $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElement ()
# Vector Add Element
# Adds the string contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorAddElementDV ()
# Vector Add Element
# Adds the string $3 in the position $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorPrint ()
# Vector Print
# Prints all the elements names and values of the vector $1 on sepparate lines

local vector_length

vector_length=$(($1_0))
if [ "$vector_length" = "0" ]; then
echo "Vector "$1" is empty!"
else
echo "Vector "$1":"
for i in $(seq 1 $vector_length); do
eval echo "[$i]: \"$$1_$i\""
###OR: eval printf '%s\n' "[$i]: \"$$1_$i\""
done
fi


VectorDestroy ()
# Vector Destroy
# Empties all the elements values of the vector $1

local vector_length

vector_length=$(($1_0))
if [ ! "$vector_length" = "0" ]; then
for i in $(seq 1 $vector_length); do
unset $1_$i
done
unset $1_0
fi


##################
### MAIN START ###
##################

## Setting vector 'params' with all the parameters received by the script:
for i in $(seq 1 $#); do
eval param="$$i"
VectorAddElementNext params param
done

# Printing the vector 'params':
VectorPrint params

read temp

## Setting vector 'params2' with the elements of the vector 'params' in reversed order:
if [ -n "$params_0" ]; then
for i in $(seq 1 $params_0); do
count=$((params_0-i+1))
VectorAddElement params2 count params_$i
done
fi

# Printing the vector 'params2':
VectorPrint params2

read temp

## Getting the values of 'params2'`s elements and printing them:
if [ -n "$params2_0" ]; then
echo "Printing the elements of the vector 'params2':"
for i in $(seq 1 $params2_0); do
eval current_elem_value="$params2_$i"
echo "params2_$i="$current_elem_value""
done
else
echo "Vector 'params2' is empty!"
fi

read temp

## Creating a two dimensional array ('a'):
for i in $(seq 1 10); do
VectorAddElement a 0 i
for j in $(seq 1 8); do
value=$(( 8 * ( i - 1 ) + j ))
VectorAddElementDV a_$i $j $value
done
done

## Manually printing the two dimensional array ('a'):
echo "Printing the two-dimensional array 'a':"
if [ -n "$a_0" ]; then
for i in $(seq 1 $a_0); do
eval current_vector_lenght=$a_$i_0
if [ -n "$current_vector_lenght" ]; then
for j in $(seq 1 $current_vector_lenght); do
eval value="$a_$i_$j"
printf "$value "
done
fi
printf "n"
done
fi

################
### MAIN END ###
################





share|improve this answer


















  • 1




    Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
    – Stéphane Chazelas
    Dec 9 '15 at 22:26











  • Thanks! I`ve edited my post.
    – user146726
    Dec 10 '15 at 1:01










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',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f137566%2farrays-in-unix-bourne-shell%23new-answer', 'question_page');

);

Post as a guest






























4 Answers
4






active

oldest

votes








4 Answers
4






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
41
down vote



accepted










/bin/sh is hardly ever a Bourne shell on any systems nowadays (even Solaris which was one of the last major system to include it has now switched to a POSIX sh for its /bin/sh in Solaris 11). /bin/sh was the Thompson shell in the early 70s. The Bourne shell replaced it in Unix V7 in 1979.



/bin/sh has been the Bourne shell for many years thereafter (or the Almquist shell, a free reimplementation on BSDs).



Nowadays, /bin/sh is more commonly an interpreter or another for the POSIX sh language which is itself based on a subset of the language of ksh88 (and a superset of the Bourne shell language with some incompatibilities).



The Bourne shell or the POSIX sh language specification don't support arrays. Or rather they have only one array: the positional parameters ($1, $2, $@, so one array per function as well).



ksh88 did have arrays which you set with set -A, but that didn't get specified in the POSIX sh as the syntax is awkward and not very usable.



Other shells with array/lists variables include: csh/tcsh, rc, es, bash (which mostly copied the ksh syntax the ksh93 way), yash, zsh, fish each with a different syntax (rc the shell of the once to-be successor of Unix, fish and zsh being the most consistent ones)...



In standard sh (also works in modern versions of the Bourne shell):



set '1st element' 2 3 # setting the array

set -- "$@" more # adding elements to the end of the array

shift 2 # removing elements (here 2) from the beginning of the array

printf '<%s>n' "$@" # passing all the elements of the $@ array
# as arguments to a command

for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"n' "$i"
done

printf '%sn' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "$10") past the 9th in other
# shells.

printf '%sn' "$# elements in the array"

printf '%sn' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)


(note that in the Bourne shell and ksh88, $IFS must contain the space character for "$@" to work properly (a bug), and in the Bourne shell, you can't access elements above $9 ($10 won't work, you can still do shift 1; echo "$9" or loop over them)).






share|improve this answer


















  • 2




    Thanks a ton...your detailed explanation was very helpful.
    – SubhasisM
    Jun 17 '14 at 10:21







  • 1




    It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
    – kojiro
    Jan 22 '16 at 16:37











  • @kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
    – Stéphane Chazelas
    Oct 23 '17 at 6:57















up vote
41
down vote



accepted










/bin/sh is hardly ever a Bourne shell on any systems nowadays (even Solaris which was one of the last major system to include it has now switched to a POSIX sh for its /bin/sh in Solaris 11). /bin/sh was the Thompson shell in the early 70s. The Bourne shell replaced it in Unix V7 in 1979.



/bin/sh has been the Bourne shell for many years thereafter (or the Almquist shell, a free reimplementation on BSDs).



Nowadays, /bin/sh is more commonly an interpreter or another for the POSIX sh language which is itself based on a subset of the language of ksh88 (and a superset of the Bourne shell language with some incompatibilities).



The Bourne shell or the POSIX sh language specification don't support arrays. Or rather they have only one array: the positional parameters ($1, $2, $@, so one array per function as well).



ksh88 did have arrays which you set with set -A, but that didn't get specified in the POSIX sh as the syntax is awkward and not very usable.



Other shells with array/lists variables include: csh/tcsh, rc, es, bash (which mostly copied the ksh syntax the ksh93 way), yash, zsh, fish each with a different syntax (rc the shell of the once to-be successor of Unix, fish and zsh being the most consistent ones)...



In standard sh (also works in modern versions of the Bourne shell):



set '1st element' 2 3 # setting the array

set -- "$@" more # adding elements to the end of the array

shift 2 # removing elements (here 2) from the beginning of the array

printf '<%s>n' "$@" # passing all the elements of the $@ array
# as arguments to a command

for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"n' "$i"
done

printf '%sn' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "$10") past the 9th in other
# shells.

printf '%sn' "$# elements in the array"

printf '%sn' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)


(note that in the Bourne shell and ksh88, $IFS must contain the space character for "$@" to work properly (a bug), and in the Bourne shell, you can't access elements above $9 ($10 won't work, you can still do shift 1; echo "$9" or loop over them)).






share|improve this answer


















  • 2




    Thanks a ton...your detailed explanation was very helpful.
    – SubhasisM
    Jun 17 '14 at 10:21







  • 1




    It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
    – kojiro
    Jan 22 '16 at 16:37











  • @kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
    – Stéphane Chazelas
    Oct 23 '17 at 6:57













up vote
41
down vote



accepted







up vote
41
down vote



accepted






/bin/sh is hardly ever a Bourne shell on any systems nowadays (even Solaris which was one of the last major system to include it has now switched to a POSIX sh for its /bin/sh in Solaris 11). /bin/sh was the Thompson shell in the early 70s. The Bourne shell replaced it in Unix V7 in 1979.



/bin/sh has been the Bourne shell for many years thereafter (or the Almquist shell, a free reimplementation on BSDs).



Nowadays, /bin/sh is more commonly an interpreter or another for the POSIX sh language which is itself based on a subset of the language of ksh88 (and a superset of the Bourne shell language with some incompatibilities).



The Bourne shell or the POSIX sh language specification don't support arrays. Or rather they have only one array: the positional parameters ($1, $2, $@, so one array per function as well).



ksh88 did have arrays which you set with set -A, but that didn't get specified in the POSIX sh as the syntax is awkward and not very usable.



Other shells with array/lists variables include: csh/tcsh, rc, es, bash (which mostly copied the ksh syntax the ksh93 way), yash, zsh, fish each with a different syntax (rc the shell of the once to-be successor of Unix, fish and zsh being the most consistent ones)...



In standard sh (also works in modern versions of the Bourne shell):



set '1st element' 2 3 # setting the array

set -- "$@" more # adding elements to the end of the array

shift 2 # removing elements (here 2) from the beginning of the array

printf '<%s>n' "$@" # passing all the elements of the $@ array
# as arguments to a command

for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"n' "$i"
done

printf '%sn' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "$10") past the 9th in other
# shells.

printf '%sn' "$# elements in the array"

printf '%sn' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)


(note that in the Bourne shell and ksh88, $IFS must contain the space character for "$@" to work properly (a bug), and in the Bourne shell, you can't access elements above $9 ($10 won't work, you can still do shift 1; echo "$9" or loop over them)).






share|improve this answer














/bin/sh is hardly ever a Bourne shell on any systems nowadays (even Solaris which was one of the last major system to include it has now switched to a POSIX sh for its /bin/sh in Solaris 11). /bin/sh was the Thompson shell in the early 70s. The Bourne shell replaced it in Unix V7 in 1979.



/bin/sh has been the Bourne shell for many years thereafter (or the Almquist shell, a free reimplementation on BSDs).



Nowadays, /bin/sh is more commonly an interpreter or another for the POSIX sh language which is itself based on a subset of the language of ksh88 (and a superset of the Bourne shell language with some incompatibilities).



The Bourne shell or the POSIX sh language specification don't support arrays. Or rather they have only one array: the positional parameters ($1, $2, $@, so one array per function as well).



ksh88 did have arrays which you set with set -A, but that didn't get specified in the POSIX sh as the syntax is awkward and not very usable.



Other shells with array/lists variables include: csh/tcsh, rc, es, bash (which mostly copied the ksh syntax the ksh93 way), yash, zsh, fish each with a different syntax (rc the shell of the once to-be successor of Unix, fish and zsh being the most consistent ones)...



In standard sh (also works in modern versions of the Bourne shell):



set '1st element' 2 3 # setting the array

set -- "$@" more # adding elements to the end of the array

shift 2 # removing elements (here 2) from the beginning of the array

printf '<%s>n' "$@" # passing all the elements of the $@ array
# as arguments to a command

for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"n' "$i"
done

printf '%sn' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "$10") past the 9th in other
# shells.

printf '%sn' "$# elements in the array"

printf '%sn' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)


(note that in the Bourne shell and ksh88, $IFS must contain the space character for "$@" to work properly (a bug), and in the Bourne shell, you can't access elements above $9 ($10 won't work, you can still do shift 1; echo "$9" or loop over them)).







share|improve this answer














share|improve this answer



share|improve this answer








edited Oct 4 at 13:08

























answered Jun 17 '14 at 9:55









Stéphane Chazelas

287k53531868




287k53531868







  • 2




    Thanks a ton...your detailed explanation was very helpful.
    – SubhasisM
    Jun 17 '14 at 10:21







  • 1




    It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
    – kojiro
    Jan 22 '16 at 16:37











  • @kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
    – Stéphane Chazelas
    Oct 23 '17 at 6:57













  • 2




    Thanks a ton...your detailed explanation was very helpful.
    – SubhasisM
    Jun 17 '14 at 10:21







  • 1




    It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
    – kojiro
    Jan 22 '16 at 16:37











  • @kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
    – Stéphane Chazelas
    Oct 23 '17 at 6:57








2




2




Thanks a ton...your detailed explanation was very helpful.
– SubhasisM
Jun 17 '14 at 10:21





Thanks a ton...your detailed explanation was very helpful.
– SubhasisM
Jun 17 '14 at 10:21





1




1




It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
– kojiro
Jan 22 '16 at 16:37





It may be worth noting that positional parameters differ from bash arrays in some key features. For example, they do not support sparse arrays, and since sh doesn't have slicing parameter expansion, you can't access sublists like "$@:2:4". To be sure, I see the similarities, but I don't regard positional parameters as an array per se.
– kojiro
Jan 22 '16 at 16:37













@kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
– Stéphane Chazelas
Oct 23 '17 at 6:57





@kojiro, to some extent, I'd say it's the contrary, "$@" acts like an array (like the arrays of csh, rc, zsh, fish, yash...), it's more the Korn/bash "arrays" that are not really arrays, but some form of associative arrays with keys limited to positive integers (they also have indices starting at 0 instead of 1 like in all other shells with arrays and "$@"). Shells that have support for slicing can slice $@ just the same (with ksh93/bash awkwardly adding $0 to the positional parameters when you slice "$@").
– Stéphane Chazelas
Oct 23 '17 at 6:57













up vote
3
down vote













There are no arrays in plain Bourne shell. You can use the following way to create an array and traverse it:



#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell

array_traverse()

for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo $$current_value)
done
return 1


ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3


No matter what way to use arrays in sh would you pick it will always be cumbersome. Consider using a different language such as Python or Perl if you can unless you are stuck with a very limited platform or want to learn something.






share|improve this answer






















  • Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
    – SubhasisM
    Jun 17 '14 at 10:51











  • @NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
    – Stéphane Chazelas
    Jun 17 '14 at 11:42











  • POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
    – Arkadiusz Drabczyk
    Jun 17 '14 at 12:17










  • @Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
    – SubhasisM
    Jun 17 '14 at 13:42







  • 2




    Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
    – Stéphane Chazelas
    Jun 17 '14 at 13:51














up vote
3
down vote













There are no arrays in plain Bourne shell. You can use the following way to create an array and traverse it:



#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell

array_traverse()

for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo $$current_value)
done
return 1


ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3


No matter what way to use arrays in sh would you pick it will always be cumbersome. Consider using a different language such as Python or Perl if you can unless you are stuck with a very limited platform or want to learn something.






share|improve this answer






















  • Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
    – SubhasisM
    Jun 17 '14 at 10:51











  • @NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
    – Stéphane Chazelas
    Jun 17 '14 at 11:42











  • POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
    – Arkadiusz Drabczyk
    Jun 17 '14 at 12:17










  • @Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
    – SubhasisM
    Jun 17 '14 at 13:42







  • 2




    Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
    – Stéphane Chazelas
    Jun 17 '14 at 13:51












up vote
3
down vote










up vote
3
down vote









There are no arrays in plain Bourne shell. You can use the following way to create an array and traverse it:



#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell

array_traverse()

for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo $$current_value)
done
return 1


ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3


No matter what way to use arrays in sh would you pick it will always be cumbersome. Consider using a different language such as Python or Perl if you can unless you are stuck with a very limited platform or want to learn something.






share|improve this answer














There are no arrays in plain Bourne shell. You can use the following way to create an array and traverse it:



#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell

array_traverse()

for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo $$current_value)
done
return 1


ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3


No matter what way to use arrays in sh would you pick it will always be cumbersome. Consider using a different language such as Python or Perl if you can unless you are stuck with a very limited platform or want to learn something.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 23 '16 at 0:10

























answered Jun 17 '14 at 10:13









Arkadiusz Drabczyk

7,34021633




7,34021633











  • Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
    – SubhasisM
    Jun 17 '14 at 10:51











  • @NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
    – Stéphane Chazelas
    Jun 17 '14 at 11:42











  • POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
    – Arkadiusz Drabczyk
    Jun 17 '14 at 12:17










  • @Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
    – SubhasisM
    Jun 17 '14 at 13:42







  • 2




    Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
    – Stéphane Chazelas
    Jun 17 '14 at 13:51
















  • Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
    – SubhasisM
    Jun 17 '14 at 10:51











  • @NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
    – Stéphane Chazelas
    Jun 17 '14 at 11:42











  • POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
    – Arkadiusz Drabczyk
    Jun 17 '14 at 12:17










  • @Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
    – SubhasisM
    Jun 17 '14 at 13:42







  • 2




    Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
    – Stéphane Chazelas
    Jun 17 '14 at 13:51















Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
– SubhasisM
Jun 17 '14 at 10:51





Thanks for the response...!! Actually I am indeed trying to learn things in shell script...otherwise implementing array in Python is really a piece of cake. This was a big lesson that there exists some scripting language which does not support array :) One thing, the code you posted is giving a error - "syntax error at line 6: `$' unexpected" ... I am a little busy now, I would get it solved...plz dont bother.
– SubhasisM
Jun 17 '14 at 10:51













@NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
– Stéphane Chazelas
Jun 17 '14 at 11:42





@NoobGeek, the Bourne shell doesn't have the $(...) syntax. So you must indeed have the Bourne shell. Are you on Solaris 10 or before? Chances are you won't have a seq either. On Solaris 10 and earlier, you want /usr/xpg4/bin/sh to have a standard sh instead of a Bourne shell. Using seq that way is not very good either.
– Stéphane Chazelas
Jun 17 '14 at 11:42













POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
– Arkadiusz Drabczyk
Jun 17 '14 at 12:17




POSIX states that $ and ` are equivalent in command substitution: link. And why is using of seq that way not good?
– Arkadiusz Drabczyk
Jun 17 '14 at 12:17












@Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
– SubhasisM
Jun 17 '14 at 13:42





@Stéphane Chazelas: Actually I am using '$' in some other script and that is working properly (var3=expr $var1 + $var2).
– SubhasisM
Jun 17 '14 at 13:42





2




2




Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
– Stéphane Chazelas
Jun 17 '14 at 13:51




Yes in POSIX shells, you should prefer $(...) over `, but the OP's /bin/sh is probably a Bourne shell, not a POSIX shell. Beside seq not being a standard command, doing $(seq 100) means storing the whole output in memory, and that means it depends on the current value of $IFS containing newline and not containing digits. Best to use i=1; while [ "$i" -le 100 ]; ...; i=$(($i + 1)); done (though that wouldn't work in the Bourne shell either).
– Stéphane Chazelas
Jun 17 '14 at 13:51










up vote
2
down vote













As the others have said, the Bourne Shell doesn't have true arrays.



However, depending on what you need to do, delimited strings should suffice:



sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%sn' "$word"
done


If the typical delimiters (space, tab, and newline) don't suffice, you can set IFS to whatever delimiter you want before the loop.



And if you need to build the array programmatically, you can just build up a delimited string.






share|improve this answer


















  • 1




    Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
    – Stéphane Chazelas
    May 13 '15 at 14:55














up vote
2
down vote













As the others have said, the Bourne Shell doesn't have true arrays.



However, depending on what you need to do, delimited strings should suffice:



sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%sn' "$word"
done


If the typical delimiters (space, tab, and newline) don't suffice, you can set IFS to whatever delimiter you want before the loop.



And if you need to build the array programmatically, you can just build up a delimited string.






share|improve this answer


















  • 1




    Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
    – Stéphane Chazelas
    May 13 '15 at 14:55












up vote
2
down vote










up vote
2
down vote









As the others have said, the Bourne Shell doesn't have true arrays.



However, depending on what you need to do, delimited strings should suffice:



sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%sn' "$word"
done


If the typical delimiters (space, tab, and newline) don't suffice, you can set IFS to whatever delimiter you want before the loop.



And if you need to build the array programmatically, you can just build up a delimited string.






share|improve this answer














As the others have said, the Bourne Shell doesn't have true arrays.



However, depending on what you need to do, delimited strings should suffice:



sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%sn' "$word"
done


If the typical delimiters (space, tab, and newline) don't suffice, you can set IFS to whatever delimiter you want before the loop.



And if you need to build the array programmatically, you can just build up a delimited string.







share|improve this answer














share|improve this answer



share|improve this answer








edited May 20 '15 at 12:58

























answered May 13 '15 at 14:08









Sildoreth

85831535




85831535







  • 1




    Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
    – Stéphane Chazelas
    May 13 '15 at 14:55












  • 1




    Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
    – Stéphane Chazelas
    May 13 '15 at 14:55







1




1




Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
– Stéphane Chazelas
May 13 '15 at 14:55




Unless you do want it (unlikely), you'll probably also want to disable globbing which is another effect of leaving variables unquoted like that (the split+glob operator).
– Stéphane Chazelas
May 13 '15 at 14:55










up vote
0
down vote













A way to simulate arrays in dash (it can be adapted for any number of dimensions of an array):
(Please note that the use of the seq command requires that IFS is set to ' ' (SPACE = the default value). You can use while ... do ... or do ... while ... loops instead to avoid this (i kept seq in the scope of a better illustration of what the code does).)



#!/bin/sh

## The following functions implement vectors (arrays) operations in dash:
## Definition of a vector <v>:
## v_0 - variable that stores the number of elements of the vector
## v_1..v_n, where n=v_0 - variables that store the values of the vector elements

VectorAddElementNext ()
# Vector Add Element Next
# Adds the string contained in variable $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElementDVNext ()
# Vector Add Element Direct Value Next
# Adds the string $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElement ()
# Vector Add Element
# Adds the string contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorAddElementDV ()
# Vector Add Element
# Adds the string $3 in the position $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorPrint ()
# Vector Print
# Prints all the elements names and values of the vector $1 on sepparate lines

local vector_length

vector_length=$(($1_0))
if [ "$vector_length" = "0" ]; then
echo "Vector "$1" is empty!"
else
echo "Vector "$1":"
for i in $(seq 1 $vector_length); do
eval echo "[$i]: \"$$1_$i\""
###OR: eval printf '%s\n' "[$i]: \"$$1_$i\""
done
fi


VectorDestroy ()
# Vector Destroy
# Empties all the elements values of the vector $1

local vector_length

vector_length=$(($1_0))
if [ ! "$vector_length" = "0" ]; then
for i in $(seq 1 $vector_length); do
unset $1_$i
done
unset $1_0
fi


##################
### MAIN START ###
##################

## Setting vector 'params' with all the parameters received by the script:
for i in $(seq 1 $#); do
eval param="$$i"
VectorAddElementNext params param
done

# Printing the vector 'params':
VectorPrint params

read temp

## Setting vector 'params2' with the elements of the vector 'params' in reversed order:
if [ -n "$params_0" ]; then
for i in $(seq 1 $params_0); do
count=$((params_0-i+1))
VectorAddElement params2 count params_$i
done
fi

# Printing the vector 'params2':
VectorPrint params2

read temp

## Getting the values of 'params2'`s elements and printing them:
if [ -n "$params2_0" ]; then
echo "Printing the elements of the vector 'params2':"
for i in $(seq 1 $params2_0); do
eval current_elem_value="$params2_$i"
echo "params2_$i="$current_elem_value""
done
else
echo "Vector 'params2' is empty!"
fi

read temp

## Creating a two dimensional array ('a'):
for i in $(seq 1 10); do
VectorAddElement a 0 i
for j in $(seq 1 8); do
value=$(( 8 * ( i - 1 ) + j ))
VectorAddElementDV a_$i $j $value
done
done

## Manually printing the two dimensional array ('a'):
echo "Printing the two-dimensional array 'a':"
if [ -n "$a_0" ]; then
for i in $(seq 1 $a_0); do
eval current_vector_lenght=$a_$i_0
if [ -n "$current_vector_lenght" ]; then
for j in $(seq 1 $current_vector_lenght); do
eval value="$a_$i_$j"
printf "$value "
done
fi
printf "n"
done
fi

################
### MAIN END ###
################





share|improve this answer


















  • 1




    Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
    – Stéphane Chazelas
    Dec 9 '15 at 22:26











  • Thanks! I`ve edited my post.
    – user146726
    Dec 10 '15 at 1:01














up vote
0
down vote













A way to simulate arrays in dash (it can be adapted for any number of dimensions of an array):
(Please note that the use of the seq command requires that IFS is set to ' ' (SPACE = the default value). You can use while ... do ... or do ... while ... loops instead to avoid this (i kept seq in the scope of a better illustration of what the code does).)



#!/bin/sh

## The following functions implement vectors (arrays) operations in dash:
## Definition of a vector <v>:
## v_0 - variable that stores the number of elements of the vector
## v_1..v_n, where n=v_0 - variables that store the values of the vector elements

VectorAddElementNext ()
# Vector Add Element Next
# Adds the string contained in variable $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElementDVNext ()
# Vector Add Element Direct Value Next
# Adds the string $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElement ()
# Vector Add Element
# Adds the string contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorAddElementDV ()
# Vector Add Element
# Adds the string $3 in the position $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorPrint ()
# Vector Print
# Prints all the elements names and values of the vector $1 on sepparate lines

local vector_length

vector_length=$(($1_0))
if [ "$vector_length" = "0" ]; then
echo "Vector "$1" is empty!"
else
echo "Vector "$1":"
for i in $(seq 1 $vector_length); do
eval echo "[$i]: \"$$1_$i\""
###OR: eval printf '%s\n' "[$i]: \"$$1_$i\""
done
fi


VectorDestroy ()
# Vector Destroy
# Empties all the elements values of the vector $1

local vector_length

vector_length=$(($1_0))
if [ ! "$vector_length" = "0" ]; then
for i in $(seq 1 $vector_length); do
unset $1_$i
done
unset $1_0
fi


##################
### MAIN START ###
##################

## Setting vector 'params' with all the parameters received by the script:
for i in $(seq 1 $#); do
eval param="$$i"
VectorAddElementNext params param
done

# Printing the vector 'params':
VectorPrint params

read temp

## Setting vector 'params2' with the elements of the vector 'params' in reversed order:
if [ -n "$params_0" ]; then
for i in $(seq 1 $params_0); do
count=$((params_0-i+1))
VectorAddElement params2 count params_$i
done
fi

# Printing the vector 'params2':
VectorPrint params2

read temp

## Getting the values of 'params2'`s elements and printing them:
if [ -n "$params2_0" ]; then
echo "Printing the elements of the vector 'params2':"
for i in $(seq 1 $params2_0); do
eval current_elem_value="$params2_$i"
echo "params2_$i="$current_elem_value""
done
else
echo "Vector 'params2' is empty!"
fi

read temp

## Creating a two dimensional array ('a'):
for i in $(seq 1 10); do
VectorAddElement a 0 i
for j in $(seq 1 8); do
value=$(( 8 * ( i - 1 ) + j ))
VectorAddElementDV a_$i $j $value
done
done

## Manually printing the two dimensional array ('a'):
echo "Printing the two-dimensional array 'a':"
if [ -n "$a_0" ]; then
for i in $(seq 1 $a_0); do
eval current_vector_lenght=$a_$i_0
if [ -n "$current_vector_lenght" ]; then
for j in $(seq 1 $current_vector_lenght); do
eval value="$a_$i_$j"
printf "$value "
done
fi
printf "n"
done
fi

################
### MAIN END ###
################





share|improve this answer


















  • 1




    Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
    – Stéphane Chazelas
    Dec 9 '15 at 22:26











  • Thanks! I`ve edited my post.
    – user146726
    Dec 10 '15 at 1:01












up vote
0
down vote










up vote
0
down vote









A way to simulate arrays in dash (it can be adapted for any number of dimensions of an array):
(Please note that the use of the seq command requires that IFS is set to ' ' (SPACE = the default value). You can use while ... do ... or do ... while ... loops instead to avoid this (i kept seq in the scope of a better illustration of what the code does).)



#!/bin/sh

## The following functions implement vectors (arrays) operations in dash:
## Definition of a vector <v>:
## v_0 - variable that stores the number of elements of the vector
## v_1..v_n, where n=v_0 - variables that store the values of the vector elements

VectorAddElementNext ()
# Vector Add Element Next
# Adds the string contained in variable $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElementDVNext ()
# Vector Add Element Direct Value Next
# Adds the string $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElement ()
# Vector Add Element
# Adds the string contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorAddElementDV ()
# Vector Add Element
# Adds the string $3 in the position $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorPrint ()
# Vector Print
# Prints all the elements names and values of the vector $1 on sepparate lines

local vector_length

vector_length=$(($1_0))
if [ "$vector_length" = "0" ]; then
echo "Vector "$1" is empty!"
else
echo "Vector "$1":"
for i in $(seq 1 $vector_length); do
eval echo "[$i]: \"$$1_$i\""
###OR: eval printf '%s\n' "[$i]: \"$$1_$i\""
done
fi


VectorDestroy ()
# Vector Destroy
# Empties all the elements values of the vector $1

local vector_length

vector_length=$(($1_0))
if [ ! "$vector_length" = "0" ]; then
for i in $(seq 1 $vector_length); do
unset $1_$i
done
unset $1_0
fi


##################
### MAIN START ###
##################

## Setting vector 'params' with all the parameters received by the script:
for i in $(seq 1 $#); do
eval param="$$i"
VectorAddElementNext params param
done

# Printing the vector 'params':
VectorPrint params

read temp

## Setting vector 'params2' with the elements of the vector 'params' in reversed order:
if [ -n "$params_0" ]; then
for i in $(seq 1 $params_0); do
count=$((params_0-i+1))
VectorAddElement params2 count params_$i
done
fi

# Printing the vector 'params2':
VectorPrint params2

read temp

## Getting the values of 'params2'`s elements and printing them:
if [ -n "$params2_0" ]; then
echo "Printing the elements of the vector 'params2':"
for i in $(seq 1 $params2_0); do
eval current_elem_value="$params2_$i"
echo "params2_$i="$current_elem_value""
done
else
echo "Vector 'params2' is empty!"
fi

read temp

## Creating a two dimensional array ('a'):
for i in $(seq 1 10); do
VectorAddElement a 0 i
for j in $(seq 1 8); do
value=$(( 8 * ( i - 1 ) + j ))
VectorAddElementDV a_$i $j $value
done
done

## Manually printing the two dimensional array ('a'):
echo "Printing the two-dimensional array 'a':"
if [ -n "$a_0" ]; then
for i in $(seq 1 $a_0); do
eval current_vector_lenght=$a_$i_0
if [ -n "$current_vector_lenght" ]; then
for j in $(seq 1 $current_vector_lenght); do
eval value="$a_$i_$j"
printf "$value "
done
fi
printf "n"
done
fi

################
### MAIN END ###
################





share|improve this answer














A way to simulate arrays in dash (it can be adapted for any number of dimensions of an array):
(Please note that the use of the seq command requires that IFS is set to ' ' (SPACE = the default value). You can use while ... do ... or do ... while ... loops instead to avoid this (i kept seq in the scope of a better illustration of what the code does).)



#!/bin/sh

## The following functions implement vectors (arrays) operations in dash:
## Definition of a vector <v>:
## v_0 - variable that stores the number of elements of the vector
## v_1..v_n, where n=v_0 - variables that store the values of the vector elements

VectorAddElementNext ()
# Vector Add Element Next
# Adds the string contained in variable $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElementDVNext ()
# Vector Add Element Direct Value Next
# Adds the string $2 in the next element position (vector length + 1) in vector $1

local elem_value
local vector_length
local elem_name

eval elem_value="$2"
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length

eval $elem_name="$elem_value"
eval $1_0=$vector_length


VectorAddElement ()
# Vector Add Element
# Adds the string contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorAddElementDV ()
# Vector Add Element
# Adds the string $3 in the position $2 (variable or direct value) in the vector $1

local elem_value
local elem_position
local vector_length
local elem_name

eval elem_value="$3"
elem_position=$(($2))
eval vector_length=$$1_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi

if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi

elem_name=$1_$elem_position

eval $elem_name="$elem_value"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi


VectorPrint ()
# Vector Print
# Prints all the elements names and values of the vector $1 on sepparate lines

local vector_length

vector_length=$(($1_0))
if [ "$vector_length" = "0" ]; then
echo "Vector "$1" is empty!"
else
echo "Vector "$1":"
for i in $(seq 1 $vector_length); do
eval echo "[$i]: \"$$1_$i\""
###OR: eval printf '%s\n' "[$i]: \"$$1_$i\""
done
fi


VectorDestroy ()
# Vector Destroy
# Empties all the elements values of the vector $1

local vector_length

vector_length=$(($1_0))
if [ ! "$vector_length" = "0" ]; then
for i in $(seq 1 $vector_length); do
unset $1_$i
done
unset $1_0
fi


##################
### MAIN START ###
##################

## Setting vector 'params' with all the parameters received by the script:
for i in $(seq 1 $#); do
eval param="$$i"
VectorAddElementNext params param
done

# Printing the vector 'params':
VectorPrint params

read temp

## Setting vector 'params2' with the elements of the vector 'params' in reversed order:
if [ -n "$params_0" ]; then
for i in $(seq 1 $params_0); do
count=$((params_0-i+1))
VectorAddElement params2 count params_$i
done
fi

# Printing the vector 'params2':
VectorPrint params2

read temp

## Getting the values of 'params2'`s elements and printing them:
if [ -n "$params2_0" ]; then
echo "Printing the elements of the vector 'params2':"
for i in $(seq 1 $params2_0); do
eval current_elem_value="$params2_$i"
echo "params2_$i="$current_elem_value""
done
else
echo "Vector 'params2' is empty!"
fi

read temp

## Creating a two dimensional array ('a'):
for i in $(seq 1 10); do
VectorAddElement a 0 i
for j in $(seq 1 8); do
value=$(( 8 * ( i - 1 ) + j ))
VectorAddElementDV a_$i $j $value
done
done

## Manually printing the two dimensional array ('a'):
echo "Printing the two-dimensional array 'a':"
if [ -n "$a_0" ]; then
for i in $(seq 1 $a_0); do
eval current_vector_lenght=$a_$i_0
if [ -n "$current_vector_lenght" ]; then
for j in $(seq 1 $current_vector_lenght); do
eval value="$a_$i_$j"
printf "$value "
done
fi
printf "n"
done
fi

################
### MAIN END ###
################






share|improve this answer














share|improve this answer



share|improve this answer








edited Aug 17 '16 at 20:56

























answered Dec 9 '15 at 16:11







user146726














  • 1




    Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
    – Stéphane Chazelas
    Dec 9 '15 at 22:26











  • Thanks! I`ve edited my post.
    – user146726
    Dec 10 '15 at 1:01












  • 1




    Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
    – Stéphane Chazelas
    Dec 9 '15 at 22:26











  • Thanks! I`ve edited my post.
    – user146726
    Dec 10 '15 at 1:01







1




1




Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
– Stéphane Chazelas
Dec 9 '15 at 22:26





Note that while local is supported by both bash and dash, it is not POSIX. seq is not a POSIX command either. You probably should mention that your code makes some assumptions on the current value of $IFS (if you avoid using seq and quote your variables, it can be avoided)
– Stéphane Chazelas
Dec 9 '15 at 22:26













Thanks! I`ve edited my post.
– user146726
Dec 10 '15 at 1:01




Thanks! I`ve edited my post.
– user146726
Dec 10 '15 at 1:01

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f137566%2farrays-in-unix-bourne-shell%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

How to check contact read email or not when send email to Individual?

Bahrain

Postfix configuration issue with fips on centos 7; mailgun relay