Remove element from bash array by content (stored in variable) without leaving a blank slot

If you want to delete the array element & shift the indices, you can use answer by l0b0 or JS웃.

However, if you don't want to shift the indices, you can use below script-let: (Particularly useful for associative arrays)

$ list=(one two three)
$ delete_me=two
$ for i in ${!list[@]};do
    if [ "${list[$i]}" == "$delete_me" ]; then
        unset list[$i]
    fi 
done

$ for i in ${!list[@]};do echo "$i = ${list[$i]}"; done
0 = one
2 = three

If you want to shift the indices to make them continuous, re-construct the array as this:

$ list=("${list[@]}")
$ for i in ${!list[@]};do echo "$i = ${list[$i]}"; done
0 = one
1 = three

You can delete an element from existing array though the whole process isn't very straightforward and may appear like a hack.

#!/bin/bash

list=( "one" "two" "three" "four" "five" )
var1="two"
var2="four"

printf "%s\n" "Before:"
for (( i=0; i<${#list[@]}; i++ )); do 
    printf "%s = %s\n" "$i" "${list[i]}"; 
done

for (( i=0; i<${#list[@]}; i++ )); do 
    if [[ ${list[i]} == $var1 || ${list[i]} == $var2 ]]; then
        list=( "${list[@]:0:$i}" "${list[@]:$((i + 1))}" )
        i=$((i - 1))
    fi
done

printf "\n%s\n" "After:"
for (( i=0; i<${#list[@]}; i++ )); do 
    printf "%s = %s\n" "$i" "${list[i]}"; 
done

This script outputs:

Before:
0 = one
1 = two
2 = three
3 = four
4 = five

After:
0 = one
1 = three
2 = five

Key part of the script is:

list=( "${list[@]:0:$i}" "${list[@]:$((i + 1))}" )

Here we re-construct your existing array by specifying the index and length to remove the element from array completely and re-order the indices.


If you want to remove by value and shift the indexes I think you have to create a new array:

list=(one two three)
new_list=() # Not strictly necessary, but added for clarity
var="two"
for item in ${list[@]}
do
    if [ "$item" != "$var" ]
    then
        new_list+=("$item")
    fi
done
list=("${new_list[@]}")
unset new_list

Test:

$ echo "${list[@]}"
one three
$ echo "${#list[@]}"
2

Tags:

Arrays

Bash

Unset