1

I am trying to write a function that removes a value from an array by value. No I do not want to remove it by index.

This is what I've tried so far.

I've seen examples outside of the function. I had to do some wonky shift thing to pass arguments to finally find the first variable and not loop through the rest and still be able to pass the array.

# Create the array.

LIST=()
LIST+=("one")
LIST+=("two")
LIST+=("three")

# List all the items.

for item in "${LIST[@]}"
do
        echo ITEM: $item
done

# Try to define the remove function.

array_remove()
{
        FIND=$1 # I'm looking for the first argument.
        echo FIND: $FIND
        DELETE=($1) # I want to delete this, I've been told to make this also an array....
        shift # I have to "shift" to make the rest work.
        ARRAY=("$@") # This is the actual second parameter.
        for target in "${ARRAY[@]}"; do
                for i in "${!ARRAY[@]}"; do
                        if [[ ${ARRAY[i]} = "${DELETE[0]}" ]]; then
                                unset 'ARRAY[i]'
                        fi  
                done
        done
        # Now at this point $ARRAY is actually correct, but I want to change $LIST.
        "$@"=$ARRAY # How???
}

# Try to remove "two" from the $LIST

array_remove "two" "${LIST[@]}"

# List all the items again, make sure they're removed.

for item in "${LIST[@]}"
do
        echo ITEM AGAIN: $item
done

This is not working out. I've tried a lot of things. I don't fundamentally understand how bash works and it's super wonky and unlike any programming language I know (and I knew a few).

The above gives me this.

ITEM: one
ITEM: two
ITEM: three
FIND: two
array.sh: line 25: one: command not found
ITEM AGAIN: one
ITEM AGAIN: two
ITEM AGAIN: three
Alexander Kleinhans
  • 5,950
  • 10
  • 55
  • 111
  • Your question seems quite similar to the one being answered here https://stackoverflow.com/a/16861932/4087040 – André Ribas Jul 28 '19 at 16:57
  • It does seem similar, but it's not in a function – Alexander Kleinhans Jul 28 '19 at 17:02
  • Just to make sure. Please confirm: You want a function that takes a string and an array name (!)(at the moment, you pass the array entries, not the array name) . The function should remove all entries matching the given string from the array. The array shall be modified. – Socowi Jul 28 '19 at 17:08
  • "The function should remove all entries matching the given string from the array. The array shall be modified." Yes – Alexander Kleinhans Jul 28 '19 at 17:13

1 Answers1

2

The only difficulty here is that you have to pass the name (!) of the array to your function and your function as to expand an array whose name is stored inside a variable. To this end you can use bash's indirection operator !:

someArray=(first second third)
nameOfTheArray='someArray[@]'
echo "$nameOfTheArray"    # prints someArray[@]
echo "${!nameOfTheArray}" # prints first second third

Now we can combine any solution from »Remove an element from a Bash array« with this indirection operator. The following function is based on this answer – in my opinion the best approach:

removeFromArray() {
    arrayName="$1"
    arrayNameAt="$arrayName"'[@]'
    removeValue="$2"
    mapfile -d '' -t "$arrayName" < <(
        printf %s\\0 "${!arrayNameAt}" | grep -zvFx "$removeValue")
}

Use this function as follows.

a=(deleteMe test deleteMe something)
removeFromArray a deleteMe
echo "${a[@]}" # prints test something
Socowi
  • 25,550
  • 3
  • 32
  • 54