Unix Arrays

kbjradmin

New Member
Messages
512
Reaction score
2
Points
0
Is there ANY way at all to tell whether or not a variable is an array in unix?
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Do you mean tell if a shell variable is an array? Unices don't have a concept of "arrays", but shells do.

In bash, "$#" tells you the length of a variable, so "${#foo[*]}" (or "${#foo[@]}") will tell you the number of items in $foo. If "[ ${#foo[*]} -gt 1 ]", then $foo is an array. In csh, tsch and zsh, use "$#foo".

Note: in bash, "$#foo" is the same as "${#foo[0]}", which is the same as the string length of the first item of $foo. Also, a non-array variable in bash can often (always?) be treated as an array of length 1. In zsh, a variable holding a string can be treated as an array of characters ("${#foo}" is the number of characters, "${foo[$i]}" is the $i-th character).
 

kbjradmin

New Member
Messages
512
Reaction score
2
Points
0
ok, but is there any way to send an array as a single argument?

for example, if someone ran a script where $var is an array:
Code:
$   somescript $var
is there some way it could be accessed, for example, like this?
Code:
#!/bin/bash
echo ${1
[*]}
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
ok, but is there any way to send an array as a single argument?

What is your end goal in all of this? When posting a question, make sure you describe the goal, not just the step. There's a decent chance you don't need arrays to do what you want to do. It looks like my guess that you were talking about shell programming was right, but I shouldn't have to guess. Always describe the environment you're dealing with (machine, OS, application, whatever). This is part of being precise and informative about your problem.

for example, if someone ran a script where $var is an array:
Code:
$   somescript $var

The man page for bash will answer all of your questions and more. `man bash`:
Referencing an array variable without a subscript is equivalent to referencing element zero.

Thus if $var holds an array, `somescript $var` is equivalent to `somescript ${var[0]}`

`man bash` said:
Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname expansion. If subscript is @ or *, the word expands to all members of name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word. When there are no array members, ${name[@]} expands to nothing.

That is, `somescript "${var[*]}"` will pass $var as a single argument to somescript while `somescript "${var[@]}"` will pass each element of $var as a separate argument.

is there some way it could be accessed, for example, like this?
Code:
#!/bin/bash
echo ${1
[*]}

What happens if you try that? You'll learn more by playing around (& reading documentation) than by asking how someone else would do something.

`man bash` said:
Special Parameters
The shell treats several parameters specially. These parameters may
only be referenced; assignment to them is not allowed.
* Expands to the positional parameters, starting from one. When
the expansion occurs within double quotes, it expands to a sin-
gle word with the value of each parameter separated by the first
character of the IFS special variable. That is, "$*" is equiva-
lent to "$1c$2c...", where c is the first character of the value
of the IFS variable. If IFS is unset, the parameters are sepa-
rated by spaces. If IFS is null, the parameters are joined
without intervening separators.
@ Expands to the positional parameters, starting from one. When
the expansion occurs within double quotes, each parameter
expands to a separate word. That is, "$@" is equivalent to "$1"
"$2" ... When there are no positional parameters, "$@" and $@
expand to nothing (i.e., they are removed).

Within a script, try:
Code:
#!/bin/bash
for i in $@; do 
  echo $i
done
and:
Code:
#!/bin/bash
for i in "$@"; do 
  echo $i
done

The following is also of interest:
`man bash` said:
Arrays are assigned to using compound assignments of the form name=(value1 ... valuen), where each value is of the form [subscript]=string.

This suggests trying:
Code:
foo="abc def ghi jkl"
bar=($foo)
from a command prompt. Now play around with $bar.
Also try the script:
Code:
#!/bin/bash
foo=($@)
echo ${#foo[*]}

Pass different things on the command line to the various scripts:
  • somescript abc def ghi
  • somescript "abc def ghi"
  • somescript "ab c" "def" "g h i"
  • foo="abc def ghi jkl" somescript $foo

Again, you might not need arrays to accomplish your goal.
 

kbjradmin

New Member
Messages
512
Reaction score
2
Points
0
Just curious, what does the @ symbol represent/how is it used?

in what context? $@ represents all of the arguments passed to a script.
Edit:
this is the script i'm writing, and i know it seems trivial, but its what i'm doing:

Code:
#!/bin/bash
#
# arraystr
# By: James Brumond
# Created: 6 February, 2009
#
# Compiles an array into a single string.
# Use:  arraystr [ -d del ]  ARRAY STRING
#
# If the -d option is passed, then the value `del`
# refers to the delimiter between the array indecies.
# If the -d option is not passed, indecies are not
# delimited at all.
#
# Exit Code Definitions:
#       161 - Too Few Args Passed.
#       162 - Too Many Args Passed.
#

helpmsg () {
        echo 'USE:  arraystr [-d del] ARRAY STRING

        OPTIONS:
                -h, --help      Displays this help message.
                -d del          Sets the delimiter to del.
                +d              Does not delimit indecies. (default)'
        exit $1
        }

startup () {
        if [ $# -eq 0 -o $1 = -h -o $1 = --help ]
        then
                helpmsg 0
        elif [ $# -eq 1 ]
        then
                echo -e "Invalid Use!\n"
                helpmsg 161
        elif [ $# -eq 2 ]
        then
                if [ $1 = -d -o $1 = +d ]
                then
                        echo -e "Invalid Use!\n"
                        helpmsg 161
                else
                        x=0
                        count=${#1
[*]}
                        while [ $x -le $count ]
                        do
                                typeset $2[$x]=`echo $2`${1[$x]}
                                x=$((++x))
                        done
                        exit 0
                fi
        elif [ $# -eq 3 ]
        then
                if [ $1 = +d ]
                then
                        x=0
                        count=${#2
[*]}
                        while [ $x -le $count ]
                        do
                                typeset $3[$x]=`echo $3`${2[$x]}
                                x=$((++x))
                        done
                        exit 0
                else
                        echo -e "Invalid Use!"
                        helpmsg 161
                fi
        elif [ $# -eq 4 ]
        then
                if [ $1 = -d ]
                then
                        :    # this part under construction...
                else
                        echo -e "Invalid Use!"
                        helpmsg 161
                fi
        else
                echo -e "Invalid Use!"
                helpmsg 162
        fi
        }

startup $@

i keep getting an error with exit status 162 (which i defined as 'too many args passed'.) so it is sending the array as seperate values even when i write it as:
Code:
arraystr ${var
[*]} other
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Your script is unnecessary.

`man bash` said:
Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname expansion. If subscript is @ or *, the word expands to all members of name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word.

That is, `somescript "${var[*]}"` will pass $var as a single argument to somescript [...]
because "${name[*]}" expands to a single word with the value of each array member separated by the first character of the IFS special variable (which is a space character by default).

See why it's good to post your overall goal along with the specific step?

If you haven't yet followed one of the links and read "How To Ask Questions The Smart Way", I recommend you do it now. If you apply the advice in that document, you'll get answers faster.
 
Last edited:

kbjradmin

New Member
Messages
512
Reaction score
2
Points
0
regardless of if there is a reason for the script or not, i'm telling you that it sends the array as separate arguments, not a single one.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
regardless of if there is a reason for the script or not, i'm telling you that it sends the array as separate arguments, not a single one.

You're right in that. ${var[*]} expands array $var to separate words and "${var[*]}" expands array $var to a single word. Same deal for $* and "$*".
 
Last edited:
Top