You are not logged in.

#1 2020-07-02 09:56:58

Awebb
Member
Registered: 2010-05-06
Posts: 6,282

[SOLVED] Synonyms in BASH's array syntax

I've been trying to clean up some old BASH scripts with a focus on consistency, where I try to increase the readability by doing things the same way if it doesn't change the outcome. Two questions have come up, that could not be solved by reading the docs:

1. Do those two lines do the same, or is there an actual difference?

declare -a SOMEARRAY=("with" "some" "elements")
SOMEARRAY=("with" "some" "elements")

2. When referencing all elements of SOMEARRAY, is there a difference between those two?

${SOMEARRAY[*]}
${SOMEARRAY[@]}

I have tried both of them and they seem to do the same, but I wonder if there are subtle differences and pitfalls.

Last edited by Awebb (2020-07-03 02:57:05)

Offline

#2 2020-07-02 10:09:36

schard
Forum Moderator
From: Hannover
Registered: 2016-05-06
Posts: 1,962
Website

Re: [SOLVED] Synonyms in BASH's array syntax

1) declare -a explicitely creates an indexed array, whereas the second statement does create it implicitely. The result is the same.
The declare statement is usually used to (just) declare variables:

declare -a SOMEARRAY
<do_stuff_with_SOMEARRAY>

So it's okay to leave it out, when you also assign an array value to the variable, which declares it implicitely.
2) The @-Syntax allows "item separation" (don't know the official term):

$ SOMEARRAY2=("with" "some" "cooler elements")
$ for ITEM in "${SOMEARRAY2[@]}"; do echo ${ITEM}; done
with
some
cooler elements
$ for ITEM in "${SOMEARRAY2[*]}"; do echo ${ITEM}; done
with some cooler elements

Note, that the double quotes around the

${SOMEARRAY2[*/@]}

statement are important here.

Last edited by schard (2020-07-02 11:36:57)

Offline

#3 2020-07-02 12:08:12

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,514
Website

Re: [SOLVED] Synonyms in BASH's array syntax

The @ and * in $SOMEARRAY[@/*] are analogs to the argv array variables $@ and $*, the functional difference is as shown by Schard.  I have mental representations of these as $* = all, and $@ = each.

Last edited by Trilby (2020-07-02 12:09:23)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#4 2020-07-02 13:55:24

eschwartz
Fellow
Registered: 2014-08-08
Posts: 4,097

Re: [SOLVED] Synonyms in BASH's array syntax

Awebb wrote:

1. Do those two lines do the same, or is there an actual difference?

declare -a SOMEARRAY=("with" "some" "elements")
SOMEARRAY=("with" "some" "elements")
  • The declare builtin will by default create a local variable, if run in a function.

  • The declare builtin permits you to evaluate the name of the array using a variable, or indeed the whole thing.

    $ arg='SOMEARRAY=("with" "some" "elements")'
    $ k='SOMEARRAY' v='("with" "some" "elements")'
    $ declare -p k v arg
    declare -- k="SOMEARRAY"
    declare -- v="(\"with\" \"some\" \"elements\")"
    declare -- arg="SOMEARRAY=(\"with\" \"some\" \"elements\")"
    
    $ declare -a "$k"="$v"
    $ declare -p SOMEARRAY 
    declare -a SOMEARRAY=([0]="with" [1]="some" [2]="elements")
    $ declare -a "$arg"
    $ declare -p SOMEARRAY 
    declare -a SOMEARRAY=([0]="with" [1]="some" [2]="elements")
    
    $ "$arg"
    bash: SOMEARRAY=("with" "some" "elements"): command not found
    $ "$k"="$v"
    bash: SOMEARRAY=("with" "some" "elements"): command not found
Awebb wrote:

2. When referencing all elements of SOMEARRAY, is there a difference between those two?

${SOMEARRAY[*]}
${SOMEARRAY[@]}

I have tried both of them and they seem to do the same, but I wonder if there are subtle differences and pitfalls.

See the Arrays section of the bash(1) manpage.

the fine manual wrote:

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. If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. This is analogous to the expansion of the special parameters * and @ (see Special Parameters above). ${#name[subscript]} expands to the length of ${name[subscript]}. If subscript is * or @, the expansion is the number of elements in the array. If the subscript used to reference an element of an indexed array evaluates to a number less than zero, it is interpreted as relative to one greater than the maximum index of the array, so negative indices count back from the end of the array, and an index of -1 references the last element.

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0. Any reference to a variable using a valid subscript is legal, and bash will create an array if necessary.


Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

#5 2020-07-03 03:10:38

Awebb
Member
Registered: 2010-05-06
Posts: 6,282

Re: [SOLVED] Synonyms in BASH's array syntax

@Schard: Thank you!

Trilby wrote:

The @ and * in $SOMEARRAY[@/*] are analogs to the argv array variables $@ and $*, the functional difference is as shown by Schard.  I have mental representations of these as $* = all, and $@ = each.

Wow, yes, argv indeed! I like that mental representation of yours!

eschwartz wrote:

The declare builtin will by default create a local variable, if run in a function.

Thanks, that's the kind of difference I was looking for (although I have a feeling I could have learned this by RTFM'ing harder).

eschwartz wrote:

The declare builtin permits you to evaluate the name of the array using a variable, or indeed the whole thing.

That's useful!

eschwartz wrote:

See the Arrays section of the bash(1) manpage.

Indeed. It's there!

Offline

Board footer

Powered by FluxBB