In bash, how do you create an indexed array, append to it, read a single element and get the number of elements — and why does `echo $arr` print only the first element?
answer
- parentheses make a list
- bare name means subscript zero
- braces are required around subscripts
- count versus character length
basics
~10 sCreate with arr=(a b c), append with arr+=(d), read one element as "${arr[0]}", count with "${#arr[@]}". A bare $arr is shorthand for ${arr[0]}, so it shows only the first element.
solid answer
~40 sAn indexed array literal is a parenthesised word list: `arr=(alpha "beta gamma" delta)`. Each word becomes one element, and quoting keeps a multi-word value in a single element. `arr+=(epsilon)` appends after the highest index. You read one element with `${arr[0]}` — the braces are mandatory, because `$arr[0]` expands `$arr` and then leaves a literal `[0]`. `${#arr[@]}` is the element count, while `${#arr}` is the character length of element 0, which is a classic trip-up. `${!arr[@]}` gives the indices, and `${arr[@]:1:2}` takes a two-element slice. Bare `$arr` is defined to mean `${arr[0]}`, so it never prints the whole array; to get every element, expand `"${arr[@]}"`. `declare -p arr` prints the real structure when you are unsure what you have.
code
bash · 9 linesarr=(alpha "beta gamma" delta)
echo "${arr[0]}" # alpha
echo "${arr[1]}" # beta gamma
echo "${#arr[@]}" # 3 (elements)
echo "${#arr}" # 5 (characters in alpha)
echo "${#arr[1]}" # 10 (characters in beta gamma)
arr+=(epsilon)
printf '%s\n' "${arr[@]:1:2}" # beta gamma / delta
declare -p arrgo deeper
Say the four basics without hesitating: arr=(a b c) creates, arr+=(d) appends, "${arr[0]}" reads, "${#arr[@]}" counts. Add that a bare $arr is only the first element.
Explain why the braces are mandatory — the subscript is part of the expansion syntax, not of the name — and distinguish ${#arr} (characters in element 0) from ${#arr[@]} (element count).
Show the habits that survive real data: quote on the way in and on the way out, use declare -p to inspect element boundaries, and know that an empty array expands to zero words rather than one empty argument.
Be ready to say where the shell's single flat list type runs out. When a script needs records, nested structures or keyed lookups threaded through many functions, argue for moving that logic to a real language rather than encoding structure into array elements.
## What an indexed array is An indexed array in bash is a variable that holds many values, each stored under an integer subscript starting at 0. It is the only built-in way to hold a list whose items may contain spaces, tabs or newlines: a plain string variable holding `a b c` is one value that only *looks* like three, and the shell will happily re-split it in ways you did not intend. ## Creating one The compound assignment is a parenthesised list of words: ```bash arr=(alpha "beta gamma" delta) ``` The words inside the parentheses go through the normal expansions, so quoting matters exactly as it does on a command line. `"beta gamma"` is one element; without the quotes it would be two. That gives three elements at indices 0, 1 and 2. You can also assign a single slot directly, `arr[7]=eta`, and bash will create the array for you. `declare -a arr` declares an empty indexed array explicitly, which is useful when a later `+=` is the first thing that touches it. ## Reading one element ```bash echo "${arr[1]}" # beta gamma ``` The braces are not optional. In `$arr[0]`, bash sees the parameter name `arr`, expands it, and leaves `[0]` as literal text, so you get `alpha[0]`. Any time a subscript is involved, the whole thing goes inside `${ }`. The subscript itself is an arithmetic context, so `${arr[i]}` works with a bare variable name and `${arr[n+1]}` does arithmetic. Bash 4.3 and later also accept negative subscripts, where `${arr[-1]}` is the last element. ## Length, count and indices Two expansions look almost identical and mean different things: ```bash echo "${#arr[@]}" # 3 -> number of elements echo "${#arr}" # 5 -> characters in ${arr[0]}, i.e. "alpha" echo "${#arr[1]}" # 10 -> characters in "beta gamma" ``` `${!arr[@]}` lists the subscripts that actually exist, which is the reliable way to iterate when the array has gaps. `${arr[@]:1:2}` is a slice of two elements starting at offset 1; `${arr[@]:1}` takes everything from offset 1 onward. ## Appending ```bash arr+=(epsilon zeta) ``` The `+=` compound assignment appends after the highest existing index — it does not overwrite and it does not care that earlier indices may be missing. This is the idiom for building a list in a loop, one `arr+=("$item")` per iteration, with the item quoted so a value containing spaces stays a single element. ## Why bare $arr is the first element Bash defines a bare array name without a subscript as equivalent to subscript 0. So `echo $arr` prints `alpha` and `arr=x` silently overwrites element 0 while leaving the rest of the array in place. There is no syntax that turns the whole array into a value except `${arr[@]}` and `${arr[*]}`, and in practice you almost always want the quoted `"${arr[@]}"`, which produces one word per element with the contents untouched. The same asymmetry explains why `${#arr}` counts characters: with no subscript, bash is measuring the string in element 0, exactly as it would for any ordinary variable. ## Inspecting what you actually have When an array is behaving oddly, print its real structure instead of guessing: ```bash declare -p arr # declare -a arr=([0]="alpha" [1]="beta gamma" [2]="delta") ``` This shows the element boundaries and the actual subscripts, which is far more informative than `echo`, where the boundaries are invisible. `printf '[%s]\n' "${arr[@]}"` is the quick equivalent: one bracketed line per element makes a stray empty element or an accidentally-merged pair obvious. ## Practical habits Quote on assignment (`arr+=("$line")`), quote on expansion (`"${arr[@]}"`), use `${#arr[@]}` for counts, and reach for `declare -p` when debugging. Those four habits cover nearly everything a script does with a list.
- What does `arr=x` do to an array that already has three elements?It assigns to element 0 only, because a bare array name means subscript 0. Elements 1 and 2 survive untouched, so the array silently ends up with a new first value and the old tail. If you meant to replace the whole thing, use `arr=(x)`, or clear it first with `unset arr`.
- How do you iterate over an array together with its indices?Loop over `"${!arr[@]}"`, which expands to the subscripts that exist, and use each one to read the value: `for i in "${!arr[@]}"; do printf '%s=%s\n' "$i" "${arr[i]}"; done`. This is correct even if some subscripts are missing, whereas a counter running from 0 to `${#arr[@]}-1` is not.
- What does `${arr[@]:1:2}` give you, and what happens if you ask for more elements than exist?It is a slice: up to two elements starting at offset 1. Asking for more than exist is not an error — you simply get however many are available, and an offset past the end yields nothing at all. A leading space is needed for a negative offset, `${arr[@]: -2}`, otherwise bash reads `:-` as the default-value operator.
saying these in an interview costs you the question
- Thinking $arr expands to the whole array
- Using ${#arr} to count elements
- Writing $arr[0] without braces
- Assuming arr+=x appends a new element
- Believing an array element cannot contain spaces