Ravindra BagaleCourses & study guides मराठी Track your progress

Shell Scripting Complete 7: Bash Arrays and Associative Arrays (declare -A) Explained Simply

An array is one variable that holds many values: a list of servers, files or ports. An associative array holds key-value pairs: server to IP, user to team, city to PIN code. This chapter teaches indexed arrays, adding and removing items, looping safely, slices, mapfile to read a file into an array, building command arguments with arrays, and associative arrays with declare -A for counting and lookups.

What you'll learn in this chapter

  • Create indexed arrays and read items
  • Add, change and remove items
  • Loop with "${arr[@]}" and indexes
  • Read files with mapfile
  • Build safe command arguments
  • Use declare -A for maps and counts

1. An everyday example: a tiffin box and a phone book

Why do we need this?

A stacked tiffin has numbered boxes: box 0 rice, box 1 dal, box 2 sabzi. You ask for 'box 1' and get dal. That is an indexed array. A phone book is different: you look up 'Ravi' and get his number. You use a name, not a number. That is an associative array.

What is it?

Tiffin = indexed array. Box number = index (starts at 0). Food in a box = element. Number of boxes = ${#arr[@]}. Phone book = associative array. Name = key. Phone number = value.

How to do it (step by step)

How to work with an arrayCreate it: a=(x y z) or declare -A mAdd: a+=(w) or m[key]=valRead one: ${a[1]} or ${m[key]}Count: ${#a[@]}Loop: for v in "${a[@]}"Remove: unset 'a[1]'
Always quote "${a[@]}".

2. Create an indexed array

Why do we need this?

A space-separated string breaks on names with spaces. An array keeps each item separate and whole.

What is it?

a=(one two 'three four') creates an array. Index starts at 0. ${a[0]} is the first item; ${a[-1]} the last (bash 4.3+). ${a[@]} is all items, ${#a[@]} the count, ${!a[@]} the indexes. Plain $a means ${a[0]} only. declare -p a shows everything.

FormGives
${a[0]}first item
${a[-1]}last item
"${a[@]}"all, each quoted
${#a[@]}count
${!a[@]}indexes
$asame as ${a[0]}

How to do it (step by step)

  1. Create and read.
cities=(Pune Mumbai 'Navi Mumbai'); echo "${cities[2]}"

Output:

Navi Mumbai

What it means: Index 2 is the third item.

  1. Count and last.
echo "${#cities[@]} cities, last is ${cities[-1]}"

Output:

3 cities, last is Navi Mumbai

What it means: -1 counts from the end.

  1. See everything.
declare -p cities

Output:

declare -a cities=([0]="Pune" [1]="Mumbai" [2]="Navi Mumbai")

What it means: Index and value pairs.

  1. Plain $name trap.
echo $cities

Output:

Pune

What it means: Only the first item.

3. Add, change and remove items

Why do we need this?

Lists grow while a script runs: failed hosts, files to upload, errors to report.

What is it?

a+=(new) appends. a[5]=x sets index 5 (arrays can have gaps). unset 'a[1]' removes item 1 but leaves a gap; rebuild with a=("${a[@]}") to renumber. a=() empties it; unset a deletes it. Quote 'a[1]' in unset so a file named a1 cannot confuse the glob.

How to do it (step by step)

  1. Append.
failed=(); failed+=(web3); failed+=(db2); echo "${failed[@]}"

Output:

web3 db2

What it means: += adds at the end.

  1. Change.
failed[0]=web4; echo "${failed[0]}"

Output:

web4

What it means: Assign by index.

  1. Remove and gap.
n=(a b c d); unset 'n[1]'; echo "${!n[@]}"

Output:

0 2 3

What it means: Index 1 is now missing.

  1. Renumber.
n=("${n[@]}"); echo "${!n[@]} -> ${n[*]}"

Output:

0 1 2 -> a c d

What it means: Rebuilt without gaps.

4. Loop over arrays safely

Why do we need this?

Most array work is a loop. The quoting decides whether names with spaces survive.

What is it?

for v in "${a[@]}" gives each item whole. for i in "${!a[@]}" gives indexes, useful when you need position or want to change items. "${a[*]}" joins all items into one string using the first char of IFS, handy for printing: (IFS=,; echo "${a[*]}").

How to do it (step by step)

  1. Each item.
files=('Q1 sales.csv' summary.csv); for f in "${files[@]}"; do echo "upload [$f]"; done

Output:

upload [Q1 sales.csv]
upload [summary.csv]

What it means: Spaces kept.

  1. Unquoted breaks.
for f in ${files[@]}; do echo "[$f]"; done

Output:

[Q1]
[sales.csv]
[summary.csv]

What it means: Never leave it unquoted.

  1. With index.
for i in "${!files[@]}"; do echo "$((i+1)). ${files[i]}"; done

Output:

1. Q1 sales.csv
2. summary.csv

What it means: Numbered list.

  1. Join with commas.
hosts=(web1 web2 db1); (IFS=,; echo "${hosts[*]}")

Output:

web1,web2,db1

What it means: IFS change stays inside ( ).

Why do we need this?

Batch processing, 'first 10' reports and checking membership are common needs.

What is it?

${a[@]:start:count} takes a slice. ${#a[2]} is the length of item 2. ${a[@]/old/new} replaces in every item. To check if a value is in an array, loop and compare, or use an associative array (faster for big lists).

How to do it (step by step)

  1. Slice.
nums=(10 20 30 40 50); echo "${nums[@]:1:3}"

Output:

20 30 40

What it means: Start at index 1, take 3.

  1. Batches of 2.
for ((i=0; i<${#nums[@]}; i+=2)); do echo "batch: ${nums[@]:i:2}"; done

Output:

batch: 10 20
batch: 30 40
batch: 50

What it means: Good for API limits.

  1. Replace in all.
imgs=(a.jpeg b.jpeg); echo "${imgs[@]/%.jpeg/.jpg}"

Output:

a.jpg b.jpg

What it means: /% matches at the end.

  1. Contains?
in_list(){ local x=$1; shift; for v in "$@"; do [[ $v == "$x" ]] && return 0; done; return 1; }; in_list db1 web1 db1 && echo found

Output:

found

What it means: Pass "${a[@]}" as arguments.

6. mapfile / readarray: file into an array

Why do we need this?

Loading a list of hosts or IDs into an array lets you count, slice and loop over it many times.

What is it?

mapfile -t arr < file puts one line per item; -t removes the new line. readarray is the same command. Feed command output with mapfile -t arr < <(cmd). -s 1 skips the first line (header), -n 10 reads at most 10. For splitting one line into words, use read -ra arr <<< "$line".

How to do it (step by step)

  1. Lines to items.
printf 'web1\nweb2\ndb1\n' | tee servers.txt; mapfile -t srv < servers.txt; echo "${#srv[@]} servers: ${srv[*]}"

Output:

3 servers: web1 web2 db1

What it means: One item per line.

  1. From a command.
mapfile -t big < <(du -sh /var/* 2>/dev/null | sort -rh | head -3); printf '%s\n' "${big[@]}"

Output:

1.2G	/var/lib
800M	/var/log
40M	/var/cache

What it means: Process substitution keeps the array.

  1. Skip header.
mapfile -t -s 1 rows < people.csv; echo "${rows[0]}"

Output:

1,Asha,Pune

What it means: -s 1 dropped the header.

  1. Split a line.
read -ra parts <<< 'mon tue wed'; echo "${parts[1]}"

Output:

tue

What it means: -a fills an array.

7. Build command arguments with arrays

Why do we need this?

Putting options in a string breaks on spaces and quotes. Arrays are the correct way to build optional flags.

What is it?

Start with args=() and add pieces: args+=(--exclude "$pat"). Run with cmd "${args[@]}". Each element is passed as exactly one argument, so spaces inside are safe. This is how professional scripts build rsync, curl and docker commands.

How to do it (step by step)

  1. String way breaks.
opts="-name 'my file.txt'"; find /tmp $opts

Output:

find: paths must precede expression: `file.txt''

What it means: Quotes inside a string are not real quotes.

  1. Array way works.
opts=(-name 'my file.txt'); find /tmp "${opts[@]}"

Output:

/tmp/my file.txt

What it means: Each element is one argument.

  1. Optional flags.
verbose=1; args=(-a); (( verbose )) && args+=(-v); args+=(--exclude '*.tmp'); echo rsync "${args[@]}" src/ dst/

Output:

rsync -a -v --exclude *.tmp src/ dst/

What it means: Flags added only when needed.

  1. See exact arguments.
printf '[%s]\n' "${args[@]}"

Output:

[-a]
[-v]
[--exclude]
[*.tmp]

What it means: *.tmp stayed one argument.

8. Associative arrays: declare -A

Why do we need this?

Lookups like 'which IP for this server' or 'which team for this user' are easy with keys instead of numbers.

What is it?

declare -A m creates one (required; bash 4+). m[key]=value sets, ${m[key]} reads, ${!m[@]} lists keys, ${#m[@]} counts. [[ -v m[key] ]] checks if a key exists. Order of keys is not guaranteed; sort them when printing. Keys can have spaces if quoted: m['Navi Mumbai']=400703.

ActionSyntax
createdeclare -A m
setm[k]=v
get${m[k]}
keys${!m[@]}
exists?[[ -v m[k] ]]
delete keyunset 'm[k]'

How to do it (step by step)

  1. Create.
declare -A pin=([Pune]=411001 [Nashik]=422001 ['Navi Mumbai']=400703); echo "${pin[Nashik]}"

Output:

422001

What it means: Look up by name.

  1. Keys and values.
for c in "${!pin[@]}"; do echo "$c=${pin[$c]}"; done | sort

Output:

Nashik=422001
Navi Mumbai=400703
Pune=411001

What it means: sort gives a stable order.

  1. Exists?
[[ -v pin[Satara] ]] && echo yes || echo 'no Satara'

Output:

no Satara

What it means: -v checks the key.

  1. Forgot declare -A.
unset m; m[web]=1; m[db]=2; declare -p m

Output:

declare -a m=([0]="2")

What it means: Treated as indexed; text keys became 0.

9. Counting and grouping with associative arrays

Why do we need this?

'How many errors per service' or 'how many hits per IP' is a daily log question.

What is it?

Use the thing you count as the key and ((count[$key]++)) in a loop. At the end print keys and counts, sorted by count with sort -k2 -nr. You can also group: list[$team]+="$user ". For very large files awk is faster, but this is clear for medium data.

How to do it (step by step)

  1. Count by status.
declare -A hits; while read -r ip _ _ _ _ _ _ _ code _; do ((hits[$code]++)); done < access.log; for k in "${!hits[@]}"; do echo "$k ${hits[$k]}"; done | sort -k2 -nr

Output:

200 912
404 37
500 4

What it means: Status code was the 9th field.

  1. Group users by team.
declare -A team; while IFS=, read -r u t; do team[$t]+="$u "; done < <(printf 'meera,dev\nkunal,ops\nasha,dev\n'); for t in "${!team[@]}"; do echo "$t: ${team[$t]}"; done | sort

Output:

dev: meera asha 
ops: kunal 

What it means: += appends text.

  1. Unique items.
declare -A seen; for x in b a b c a; do seen[$x]=1; done; echo "${!seen[@]}" | tr ' ' '\n' | sort | tr '\n' ' '

Output:

a b c 

What it means: Keys are unique by nature.

10. Real examples from many industries

Why do we need this?

The same Linux skill shows up in every kind of company. Seeing it in many places helps you remember it.

What is it?

Each row is a made-up team. It shows who uses this and how.

How to do it (step by step)

Team and cityHow they use itCommand
Aditi, e-commerce, PuneServer to IP map for deploydeclare -A ip=([web1]=10.0.1.5)
Ben, broadcasting, Londonrsync args built in an arrayrsync "${args[@]}"
Min-jun, gaming, SeoulCount errors per service((cnt[$svc]++))
Layla, airline, CairoHost list via mapfilemapfile -t hosts < hosts.txt
Mateo, fintech, Buenos AiresBatch API calls in slices${ids[@]:i:50}
Swapnil, insurance, NagpurCollect failures and reportfailed+=("$h")

11. Common errors and how to fix them

Why do we need this?

Everyone hits these errors. Knowing the cause saves hours.

What is it?

Read the exact message first. Then match it to a row below.

How to do it (step by step)

Error you seeWhy it happensHow to fix
Only first item printedUsed $a instead of "${a[@]}"Use "${a[@]}".
echo "${a[@]}"
Items with spaces splitUnquoted ${a[@]}Quote it.
for x in "${a[@]}"
Text keys collapsed to [0]No declare -ADeclare first.
declare -A m
declare: -A: invalid optionOld bash 3 (macOS)Install bash 4+.
brew install bash
bad array subscriptEmpty keyCheck key is not empty.
[[ -n $k ]] && m[$k]=1
Array empty after pipe | whileSubshell lost itUse < <(cmd) or mapfile.
mapfile -t a < <(cmd)
New line at end of every itemmapfile without -tAdd -t.
mapfile -t a < f
unbound variable with set -u on empty arrayOld bash and empty arrayUse ${a[@]+"${a[@]}"} or bash 4.4+.
echo ${a[@]+"${a[@]}"}
Arguments wrong when stored in a stringString instead of arrayBuild an array.
args=(-name "$n")

12. Troubleshooting step by step

Why do we need this?

declare -p shows exactly what an array holds, including type and indexes.

What is it?

Go top to bottom. Stop at the first step that shows the problem.

How to do it (step by step)

  1. Dump it.
declare -p a
  1. Count.
echo ${#a[@]}
  1. Each item boxed.
printf '[%s]\n' "${a[@]}"
  1. Indexes.
echo "${!a[@]}"
  1. Bash version.
echo $BASH_VERSION
  1. Lint.
shellcheck s.sh

13. Lab 1: Server inventory with arrays

Why do we need this?

Load servers with mapfile, ping them, collect failures in an array and print a summary.

What is it?

A full hands-on lab. Run every step on a test Linux machine (an EC2 instance, a VM, or WSL).

How to do it (step by step)

  1. Folder.
mkdir -p ~/lab43 && cd ~/lab43 && printf 'localhost\n127.0.0.1\nno.such.host\n' | tee inv.txt
  1. Load.
mapfile -t inv < inv.txt; echo "${#inv[@]} servers"

Output:

3 servers
  1. Check.
ok=(); bad=(); for h in "${inv[@]}"; do if ping -c1 -W1 "$h" &>/dev/null; then ok+=("$h"); else bad+=("$h"); fi; done
  1. Summary.
echo "up=${#ok[@]} down=${#bad[@]}"; printf 'DOWN: %s\n' "${bad[@]}"

Output:

up=2 down=1
DOWN: no.such.host
  1. Join.
(IFS=,; echo "up: ${ok[*]}")

Output:

up: localhost,127.0.0.1
  1. Inspect.
declare -p bad

Output:

declare -a bad=([0]="no.such.host")

14. Lab 2: Count by key with declare -A

Why do we need this?

Count login shells used on the system and map users to shells.

What is it?

A full hands-on lab. Run every step on a test Linux machine (an EC2 instance, a VM, or WSL).

How to do it (step by step)

  1. Declare.
declare -A cnt usr
  1. Read passwd.
while IFS=: read -r u _ _ _ _ _ sh; do ((cnt[$sh]++)); usr[$u]=$sh; done < /etc/passwd
  1. Counts.
for s in "${!cnt[@]}"; do echo "${cnt[$s]} $s"; done | sort -nr

Output:

22 /usr/sbin/nologin
3 /bin/bash
1 /bin/sync
  1. Lookup.
echo "root uses ${usr[root]}"

Output:

root uses /bin/bash
  1. Exists?
[[ -v usr[nobody99] ]] || echo 'no such user'

Output:

no such user
  1. Total keys.
echo "${#usr[@]} users, ${#cnt[@]} shells"

Output:

26 users, 3 shells

Ravindra Bagale's Tip

Store lists in arrays, not in space-separated strings, and always expand them as "${arr[@]}". When you need lookups by name or counts, use declare -A and remember to declare it first.

15. Frequently asked questions

Q. Index starts at?

0.

Q. "${a[@]}" vs "${a[*]}"?

Separate items vs one joined string.

Q. Sort an array?

mapfile -t s < <(printf '%s\n' "${a[@]}" | sort).

Q. Arrays in sh?

No; bash, zsh, ksh only.

Q. Pass an array to a function?

As "${a[@]}" or by nameref.

Q. Export an array?

Not possible; write to a file.

Q. Key order?

Not guaranteed; sort.

Q. 2D arrays?

Fake with keys like m[row,col].

16. Interview questions and answers

Beginner level

Q. Create an array?

a=(x y z).

Q. Number of items?

${#a[@]}.

Q. Add an item?

a+=(new).

Q. First item?

${a[0]}.

Mid level level

Q. Loop safely?

for x in "${a[@]}".

Q. File into array?

mapfile -t a < file.

Q. Associative array?

declare -A m; m[k]=v.

Q. Check a key?

[[ -v m[k] ]].

Senior level

Q. Why build commands in arrays?

Each element is one argument, safe with spaces.

Q. unset leaves gaps; how to fix?

a=("${a[@]}").

Q. Arrays vs awk for counting?

Arrays clear for medium data; awk faster for huge files.

Q. Portability concerns?

bash 4+ for -A; macOS ships bash 3.2.

Try at home

  1. Put five of your favourite places in an array and print them numbered, then remove the third one and print again.
  2. Use declare -A to count how many files of each extension are in your home folder.

Practice Tasks

About this scenario

Nairobi Ride is a transport business in Nairobi. Wanjiru Kamau looks after its IT and cloud work. They count money in KES and run their AWS resources in the af-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 21

Easy Make an array

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Create an array zones with the items east west north.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy First item

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print the first item of the array zones.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Last item

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print the last item of the array zones using a negative index.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy All items

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print all items of the array zones, each quoted.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Count

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print how many items the array zones has.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Append

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Add south to the end of the array zones.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Inspect

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Show the full definition of the array zones.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Make a map

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Create an empty associative array named stockqty.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Easy Set a key

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Set the key rice in the map stockqty to 40.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Indexes

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print the indexes of the array zones.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Set index 3

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Set index 3 of the array zones to central.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Remove item 1

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Remove index 1 from the array zones, quoting the element.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Loop items

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Loop over the array zones printing each item, variable z.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Slice

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print 2 items of the array zones starting at index 1.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium File into array

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Read vendors.txt into the array vend, one line per item, without new lines.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium List keys

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print all keys of the map stockqty.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Medium Key exists

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Print yes if the key dal exists in stockqty.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Hard Close the gaps

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Rebuild the array zones so its indexes have no gaps.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Hard Join with pipe

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: In a subshell, print all items of zones joined with |.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Hard Command into array

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Load the output of ls /etc/cron.d into the array jobs, without new lines.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

Hard Count up

Why: BIZ keeps lists of servers, users and counts in arrays.

What to do: Increase the count for the key held in $code inside the map hitsby by one.

How:
  1. Find the Linux command that does this job.
  2. Add the options (like -r or -h) the task needs.
  3. Add the file names, folders or users in the right order.
  4. Use sudo if the job changes system files or users. Click Check answer.

In short

  1. a=(x y) creates; index from 0.
  2. "${a[@]}" all items, ${#a[@]} count, ${!a[@]} indexes.
  3. a+=(x) adds; unset 'a[i]' removes.
  4. mapfile -t loads a file.
  5. Build command args with arrays.
  6. declare -A for keys, lookups and counts.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

Arrays in 4 steps. Create. One item. Count. Loop.
Revision card: Arrays in 4 steps · Download PNG · Open card page
Associative arrays. Declare first. Set a key. Read a key. All keys.
Revision card: Associative arrays · Download PNG · Open card page
indexed vs associative. Numbered 0, 1, 2. / Named keys.
Comparison: indexed vs associative · Download PNG · Open card page
mapfile vs while read. All lines at once. / One line at a time.
Comparison: mapfile vs while read · Download PNG · Open card page
${a[@]} vs ${a[*]}?. "${a[@]}" keeps items separate. "${a[*]}" joins into one string. Loop safely.
Interview card: ${a[@]} vs ${a[*]}? · Download PNG · Open card page
File lines into an array?. mapfile reads all lines. -t drops newlines. Example.
Interview card: File lines into an array? · Download PNG · Open card page
Count words with bash only?. declare -A counter. Add one per word. Print keys and values.
Interview card: Count words with bash only? · Download PNG · Open card page
declare -A fails on Mac?. macOS ships bash 3.2. Associative arrays need bash 4+. Check.
Interview card: declare -A fails on Mac? · Download PNG · Open card page

More cards: Ravi Sir's Cards.