Bash remove from array: one element, first item, duplicates, and subtract another array

Bash patterns to remove an element from an array, drop the first item, dedupe (bash array remove duplicates), and subtract all values of one array from another using loops or an associative map.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

Bash remove from array: one element, first item, duplicates, and subtract another array

bash remove element from array and bash remove item from array usually mean either “drop this value”, “drop the first/last slot”, bash array remove duplicates, or “everything in A that is not listed in B” (the original title of this page). Pick one job; mixing them is how scripts grow grep pipes that break on spaces. If your data started as a string, split first with bash split string into array.

Snippets below were run with Bash 5.2.37 on Ubuntu 25.04 (kernel 6.14.0-37-generic).


bash remove item from array (filter by value)

Build a new array and skip the value you do not want—safe with spaces and glob characters because the array stays quoted:

bash
array1=(a b c d)
remove=b
filtered=()
for item in "${array1[@]}"; do
  [[ $item == "$remove" ]] && continue
  filtered+=("$item")
done
printf '%s ' "${filtered[@]}"
echo
text
a c d

That is the usual answer to bash remove from array / remove element from array bash when you only remove one known token.


bash remove first element from array (or tail by slice)

Slices are the fast path for “drop head or tail” without scanning:

bash
nums=(10 20 30 40)
rest=("${nums[@]:1}")     # drop first
echo "${rest[@]}"
text
20 30 40

Drop the last element on Bash 4.3+:

bash
nums=(10 20 30)
unset 'nums[-1]'
echo "${nums[@]}"
text
10 20

bash array remove duplicates (uniq, or order-preserving map)

Sorted input, order not important:

bash
vals=(b a b c a)
printf '%s\n' "${vals[@]}" | sort -u
text
a
b
c

bash remove duplicates from array while keeping first-seen order needs an associative array (Bash 4+):

bash
vals=(a b a c b)
declare -A seen=()
deduped=()
for v in "${vals[@]}"; do
  [[ -n ${seen[$v]+isset} ]] && continue
  seen[$v]=1
  deduped+=("$v")
done
printf '%s ' "${deduped[@]}"
echo
text
a b c

Delete elements of one array from another (set difference A \ B)

Mark everything in B, walk A, skip hits—O(n) and robust for arbitrary strings (unlike ${a[@]/x/} tricks that leave empty slots or partial substring matches):

bash
A=(a b c d)
B=(b e)
declare -A drop=()
for x in "${B[@]}"; do drop[$x]=1; done
out=()
for x in "${A[@]}"; do
  [[ -n ${drop[$x]+isset} ]] && continue
  out+=("$x")
done
printf '%s ' "${out[@]}"
echo
text
a c d

That is the clean bash remove item from list pattern when the “list” to remove lives in a second array.


Why not ${array[@]/pattern/} for removal?

${arr[@]/b/} substitutes substring matches inside every element and can leave empty entries ("") instead of removing a slot. It also treats patterns as substrings, not “whole cell equals b”. Prefer explicit loops or an associative map.


comm / grep shortcuts (when data is simple)

If every token is a single word with no spaces, sorted comm -23 can print A \ B:

bash
A=(a b c d)
B=(b e)
comm -23 <(printf '%s\n' "${A[@]}" | sort) <(printf '%s\n' "${B[@]}" | sort) | paste -sd' ' -
text
a c d

Keep the map version when elements can contain spaces or you care about original order.



Summary

Use a quoted loop for bash remove element from array by value, "${arr[@]:1}" or unset 'arr[-1]' for bash remove first element from array (or trimming the tail), sort -u or an declare -A pass for bash array remove duplicates / bash remove duplicates from array, and an associative “drop set” for delete elements of one array from another. Avoid ${array[@]/x/} unless you truly want substring substitution with possible empty cells; prefer explicit tests for bash remove item from list clarity.

Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …