Remove an element from a Bash arrayRemove element from bash array by content (stored in variable) without leaving a blank slotbash: Remove variable from array?Remove value from array bashHow do you unset all empty array elements in bash?Remove multiple elements from array based on indexHow can I compile all .cpp files except one using g++?Bash, remove a value from an array (by value) (in a function)Get the source directory of a Bash script from within the script itselfCreate ArrayList from arrayHow to append something to an array?Deleting an element from an array in PHPHow to check if a program exists from a Bash script?How do I tell if a regular file does not exist in Bash?How to concatenate string variables in BashHow do I remove a particular element from an array in JavaScript?Loop through an array of strings in Bash?For-each over an array in JavaScript?
Using Python in a Bash Script
Exploiting the delay when a festival ticket is scanned
Should I put my name first, or last in the team members list
What would the United Kingdom's "optimal" Brexit deal look like?
What are the closest international airports in different countries?
Can you continue the movement of a Bonus Action Dash granted by Expeditious Retreat if your Concentration is broken mid-move?
How can flights operated by the same company have such different prices when marketed by another?
How would a lunar colony attack Earth?
Spider-Man and Fantastic 4 crossover comic with Double Identity Scene
Why does calling cout.operator<<(const char*) print the address instead of the character string?
On the sensitivity conjecture?
Avoiding Implicit Conversion in Constructor. Explicit keyword doesn't help here
How to innovate in OR
Why are prop blades not shaped like household fan blades?
Reading electrical clamp tester higher voltage/amp 400A
How to prevent a single-element caster from being useless against immune foes?
Can a US President, after impeachment and removal, be re-elected or re-appointed?
How should I quote American English speakers in a British English essay?
Move arrows along a contour
Why would anyone ever invest in a cash-only etf?
How to foreshadow to avoid a 'deus ex machina'-construction
What is a good example for artistic ND filter applications?
Efficiently finding furthest two nodes in a graph
Unknown indication below upper stave
Remove an element from a Bash array
Remove element from bash array by content (stored in variable) without leaving a blank slotbash: Remove variable from array?Remove value from array bashHow do you unset all empty array elements in bash?Remove multiple elements from array based on indexHow can I compile all .cpp files except one using g++?Bash, remove a value from an array (by value) (in a function)Get the source directory of a Bash script from within the script itselfCreate ArrayList from arrayHow to append something to an array?Deleting an element from an array in PHPHow to check if a program exists from a Bash script?How do I tell if a regular file does not exist in Bash?How to concatenate string variables in BashHow do I remove a particular element from an array in JavaScript?Loop through an array of strings in Bash?For-each over an array in JavaScript?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I need to remove an element from an array in bash shell.
Generally I'd simply do:
array=("$(@)array:#<element to remove>")
Unfortunately the element I want to remove is a variable so I can't use the previous command.
Down here an example:
array+=(pluto)
array+=(pippo)
delete=(pluto)
array( $array[@]/$delete ) -> but clearly doesn't work because of
Any idea?
arrays bash variables
add a comment |
I need to remove an element from an array in bash shell.
Generally I'd simply do:
array=("$(@)array:#<element to remove>")
Unfortunately the element I want to remove is a variable so I can't use the previous command.
Down here an example:
array+=(pluto)
array+=(pippo)
delete=(pluto)
array( $array[@]/$delete ) -> but clearly doesn't work because of
Any idea?
arrays bash variables
Which shell? Your example looks likezsh
.
– chepner
May 31 '13 at 16:30
array=( $array[@]/$delete )
works as expected in Bash. Have you simply missed the=
?
– Ken Sharp
Jan 17 '18 at 19:56
@Ken, that's not quite what's wanted - it will remove any matches from each string, and leave empty strings in the array where it matches the whole string.
– Toby Speight
Feb 27 at 15:05
add a comment |
I need to remove an element from an array in bash shell.
Generally I'd simply do:
array=("$(@)array:#<element to remove>")
Unfortunately the element I want to remove is a variable so I can't use the previous command.
Down here an example:
array+=(pluto)
array+=(pippo)
delete=(pluto)
array( $array[@]/$delete ) -> but clearly doesn't work because of
Any idea?
arrays bash variables
I need to remove an element from an array in bash shell.
Generally I'd simply do:
array=("$(@)array:#<element to remove>")
Unfortunately the element I want to remove is a variable so I can't use the previous command.
Down here an example:
array+=(pluto)
array+=(pippo)
delete=(pluto)
array( $array[@]/$delete ) -> but clearly doesn't work because of
Any idea?
arrays bash variables
arrays bash variables
edited Sep 15 '18 at 1:16
codeforester
20.1k8 gold badges44 silver badges75 bronze badges
20.1k8 gold badges44 silver badges75 bronze badges
asked May 31 '13 at 15:31
AlexAlex
4121 gold badge4 silver badges6 bronze badges
4121 gold badge4 silver badges6 bronze badges
Which shell? Your example looks likezsh
.
– chepner
May 31 '13 at 16:30
array=( $array[@]/$delete )
works as expected in Bash. Have you simply missed the=
?
– Ken Sharp
Jan 17 '18 at 19:56
@Ken, that's not quite what's wanted - it will remove any matches from each string, and leave empty strings in the array where it matches the whole string.
– Toby Speight
Feb 27 at 15:05
add a comment |
Which shell? Your example looks likezsh
.
– chepner
May 31 '13 at 16:30
array=( $array[@]/$delete )
works as expected in Bash. Have you simply missed the=
?
– Ken Sharp
Jan 17 '18 at 19:56
@Ken, that's not quite what's wanted - it will remove any matches from each string, and leave empty strings in the array where it matches the whole string.
– Toby Speight
Feb 27 at 15:05
Which shell? Your example looks like
zsh
.– chepner
May 31 '13 at 16:30
Which shell? Your example looks like
zsh
.– chepner
May 31 '13 at 16:30
array=( $array[@]/$delete )
works as expected in Bash. Have you simply missed the =
?– Ken Sharp
Jan 17 '18 at 19:56
array=( $array[@]/$delete )
works as expected in Bash. Have you simply missed the =
?– Ken Sharp
Jan 17 '18 at 19:56
@Ken, that's not quite what's wanted - it will remove any matches from each string, and leave empty strings in the array where it matches the whole string.
– Toby Speight
Feb 27 at 15:05
@Ken, that's not quite what's wanted - it will remove any matches from each string, and leave empty strings in the array where it matches the whole string.
– Toby Speight
Feb 27 at 15:05
add a comment |
18 Answers
18
active
oldest
votes
The following works as you would like in bash
and zsh
:
$ array=(pluto pippo)
$ delete=(pluto)
$ echo $array[@]/$delete
pippo
$ array=( "$array[@]/$delete" ) #Quotes when working with strings
If need to delete more than one element:
...
$ delete=(pluto pippo)
for del in $delete[@]
do
array=("$array[@]/$del") #Quotes when working with strings
done
Caveat
This technique actually removes prefixes matching $delete
from the elements, not necessarily whole elements.
Update
To really remove an exact item, you need to walk through the array, comparing the target to each element, and using unset
to delete an exact match.
array=(pluto pippo bob)
delete=(pippo)
for target in "$delete[@]"; do
for i in "$!array[@]"; do
if [[ $array[i] = "$delete[0]" ]]; then
unset 'array[i]'
fi
done
done
Note that if you do this, and one or more elements is removed, the indices will no longer be a continuous sequence of integers.
$ declare -p array
declare -a array=([0]="pluto" [2]="bob")
The simple fact is, arrays were not designed for use as mutable data structures. They are primarily used for storing lists of items in a single variable without needing to waste a character as a delimiter (e.g., to store a list of strings which can contain whitespace).
If gaps are a problem, then you need to rebuild the array to fill the gaps:
for i in "$!array[@]"; do
new_array+=( "$array[i]" )
done
array=("$new_array[@]")
unset new_array
31
just know that:$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results inflower
– bernstein
Mar 26 '14 at 14:41
9
Note that this is actually doing a substitution, so if the array is something like(pluto1 pluto2 pippo)
then you will end up with(1 2 pippo)
.
– haridsv
Sep 22 '14 at 5:22
2
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something likefor element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
2
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
3
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
|
show 9 more comments
You could build up a new array without the undesired element, then assign it back to the old array. This works in bash
:
array=(pluto pippo)
new_array=()
for value in "$array[@]"
do
[[ $value != pluto ]] && new_array+=($value)
done
array=("$new_array[@]")
unset new_array
This yields:
echo "$array[@]"
pippo
add a comment |
This is the most direct way to unset a value if you know it's position.
$ array=(one two three)
$ echo $#array[@]
3
$ unset 'array[1]'
$ echo $array[@]
one three
$ echo $#array[@]
2
3
Tryecho $array[1]
, you will get null string. And to getthree
you need to doecho $array[2]
. Sounset
is not the right mechanism to remove an element in bash array.
– rashok
Apr 3 '18 at 9:23
add a comment |
Here's a one-line solution with mapfile:
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "<regexp>")
Example:
$ arr=("Adam" "Bob" "Claire"$'n'"Smith" "David" "Eve" "Fred")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 6 Contents: Adam Bob Claire
Smith David Eve Fred
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "^ClairenSmith$")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 5 Contents: Adam Bob David Eve Fred
This method allows for great flexibility by modifying/exchanging the grep command and doesn't leave any empty strings in the array.
1
Please useprintf '%sn' "$array[@]"
instead of that uglyIFS
/echo
thing.
– gniourf_gniourf
Jan 15 '17 at 19:07
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
@Socowi You're incorrect, at least on bash 4.4.19.-d $''
works perfectly fine while just-d
without the argument does not.
– Niklas Holm
Mar 27 at 9:13
Ah yes, I mixed it up. Sorry. What I meant was:-d $''
is the same as-d $' something'
or just-d ''
.
– Socowi
Mar 27 at 9:27
|
show 1 more comment
To expand on the above answers, the following can be used to remove multiple elements from an array, without partial matching:
ARRAY=(one two onetwo three four threefour "one six")
TO_REMOVE=(one four)
TEMP_ARRAY=()
for pkg in "$ARRAY[@]"; do
for remove in "$TO_REMOVE[@]"; do
KEEP=true
if [[ $pkg == $remove ]]; then
KEEP=false
break
fi
done
if $KEEP; then
TEMP_ARRAY+=($pkg)
fi
done
ARRAY=("$TEMP_ARRAY[@]")
unset TEMP_ARRAY
This will result in an array containing:
(two onetwo three threefour "one six")
add a comment |
Here's a (probably very bash-specific) little function involving bash variable indirection and unset
; it's a general solution that does not involve text substitution or discarding empty elements and has no problems with quoting/whitespace etc.
delete_ary_elmt()
local word=$1 # the element to search for & delete
local aryref="$2[@]" # a necessary step since '$!$2[@]' is a syntax error
local arycopy=("$!aryref") # create a copy of the input array
local status=1
for (( i = $#arycopy[@] - 1; i >= 0; i-- )); do # iterate over indices backwards
elmt=$arycopy[$i]
[[ $elmt == $word ]] && unset "$2[$i]" && status=0 # unset matching elmts in orig. ary
done
return $status # return 0 if something was deleted; 1 if not
array=(a 0 0 b 0 0 0 c 0 d e 0 0 0)
delete_ary_elmt 0 array
for e in "$array[@]"; do
echo "$e"
done
# prints "a" "b" "c" "d" in lines
Use it like delete_ary_elmt ELEMENT ARRAYNAME
without any $
sigil. Switch the == $word
for == $word*
for prefix matches; use $elmt,, == $word,,
for case-insensitive matches; etc., whatever bash [[
supports.
It works by determining the indices of the input array and iterating over them backwards (so deleting elements doesn't screw up iteration order). To get the indices you need to access the input array by name, which can be done via bash variable indirection x=1; varname=x; echo $!varname # prints "1"
.
You can't access arrays by name like aryname=a; echo "$$aryname[@]
, this gives you an error. You can't do aryname=a; echo "$!aryname[@]"
, this gives you the indices of the variable aryname
(although it is not an array). What DOES work is aryref="a[@]"; echo "$!aryref"
, which will print the elements of the array a
, preserving shell-word quoting and whitespace exactly like echo "$a[@]"
. But this only works for printing the elements of an array, not for printing its length or indices (aryref="!a[@]"
or aryref="#a[@]"
or "$!!aryref"
or "$#!aryref"
, they all fail).
So I copy the original array by its name via bash indirection and get the indices from the copy. To iterate over the indices in reverse I use a C-style for loop. I could also do it by accessing the indices via $!arycopy[@]
and reversing them with tac
, which is a cat
that turns around the input line order.
A function solution without variable indirection would probably have to involve eval
, which may or may not be safe to use in that situation (I can't tell).
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try runningdelete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.
– Scott
Feb 26 '18 at 19:26
add a comment |
Using unset
To remove an element at particular index, we can use unset
and then do copy to another array. Only just unset
is not required in this case. Because unset
does not remove the element it just sets null string to the particular index in array.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in "$arr[@]"
do
arr2[$i]=$element
((++i))
done
echo "$arr[@]"
echo "1st val is $arr[1], 2nd val is $arr[2]"
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd
Using :<idx>
We can remove some set of elements using :<idx>
also. For example if we want to remove 1st element we can use :1
as mentioned below.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
arr2=("$arr[@]:1")
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
bb cc dd ee
1st val is cc, 2nd val is dd
add a comment |
POSIX shell script does not have arrays.
So most probably you are using a specific dialect such as bash
, korn shells or zsh
.
Therefore, your question as of now cannot be answered.
Maybe this works for you:
unset array[$delete]
2
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
add a comment |
Actually, I just noticed that the shell syntax somewhat has a behavior built-in that allows for easy reconstruction of the array when, as posed in the question, an item should be removed.
# let's set up an array of items to consume:
x=()
for (( i=0; i<10; i++ )); do
x+=("$i")
done
# here, we consume that array:
while (( $#x[@] )); do
i=$(( $RANDOM % $#x[@] ))
echo "$x[i] / $x[@]"
x=("$x[@]:0:i" "$x[@]:i+1")
done
Notice how we constructed the array using bash's x+=()
syntax?
You could actually add more than one item with that, the content of a whole other array at once.
add a comment |
http://wiki.bash-hackers.org/syntax/pe#substring_removal
$PARAMETER#PATTERN # remove from beginning
$PARAMETER##PATTERN # remove from the beginning, greedy match
$PARAMETER%PATTERN # remove from the end
$PARAMETER%%PATTERN # remove from the end, greedy match
In order to do a full remove element, you have to do an unset command with an if statement. If you don't care about removing prefixes from other variables or about supporting whitespace in the array, then you can just drop the quotes and forget about for loops.
See example below for a few different ways to clean up an array.
options=("foo" "bar" "foo" "foobar" "foo bar" "bars" "bar")
# remove bar from the start of each element
options=("$options[@]/#"bar"")
# options=("foo" "" "foo" "foobar" "foo bar" "s" "")
# remove the complete string "foo" in a for loop
count=$#options[@]
for ((i = 0; i < count; i++)); do
if [ "$options[i]" = "foo" ] ; then
unset 'options[i]'
fi
done
# options=( "" "foobar" "foo bar" "s" "")
# remove empty options
# note the count variable can't be recalculated easily on a sparse array
for ((i = 0; i < count; i++)); do
# echo "Element $i: '$options[i]'"
if [ -z "$options[i]" ] ; then
unset 'options[i]'
fi
done
# options=("foobar" "foo bar" "s")
# list them with select
echo "Choose an option:"
PS3='Option? '
select i in "$options[@]" Quit
do
case $i in
Quit) break ;;
*) echo "You selected "$i"" ;;
esac
done
Output
Choose an option:
1) foobar
2) foo bar
3) s
4) Quit
Option?
Hope that helps.
add a comment |
In ZSH this is dead easy (note this uses more bash compatible syntax than necessary where possible for ease of understanding):
# I always include an edge case to make sure each element
# is not being word split.
start=(one two three 'four 4' five)
work=($(@)start)
idx=2
val=$work[idx]
# How to remove a single element easily.
# Also works for associative arrays (at least in zsh)
work[$idx]=()
echo "Array size went down by one: "
[[ $#work -eq $(($#start - 1)) ]] && echo "OK"
echo "Array item "$val" is now gone: "
[[ -z $work[(r)$val] ]] && echo OK
echo "Array contents are as expected: "
wanted=("$start[@]:0:1" "$start[@]:2")
[[ "$(j.:.)wanted[@]" == "$(j.:.)work[@]" ]] && echo "OK"
echo "-- array contents: start --"
print -l -r -- "-- $#start elements" $(@)start
echo "-- array contents: work --"
print -l -r -- "-- $#work elements" "$work[@]"
Results:
Array size went down by one:
OK
Array item two is now gone:
OK
Array contents are as expected:
OK
-- array contents: start --
-- 5 elements
one
two
three
four 4
five
-- array contents: work --
-- 4 elements
one
three
four 4
five
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
add a comment |
There is also this syntax, e.g. if you want to delete the 2nd element :
array=("$array[@]:0:1" "$array[@]:2")
which is in fact the concatenation of 2 tabs. The first from the index 0 to the index 1 (exclusive) and the 2nd from the index 2 to the end.
add a comment |
Partial answer only
To delete the first item in the array
unset 'array[0]'
To delete the last item in the array
unset 'array[-1]'
add a comment |
To avoid conflicts with array index using unset
- see https://stackoverflow.com/a/49626928/3223785 and https://stackoverflow.com/a/47798640/3223785 for more information - reassign the array to itself: ARRAY_VAR=($ARRAY_VAR[@])
.
#!/bin/bash
ARRAY_VAR=(0 1 2 3 4 5 6 7 8 9)
unset ARRAY_VAR[5]
unset ARRAY_VAR[4]
ARRAY_VAR=($ARRAY_VAR[@])
echo $ARRAY_VAR[@]
A_LENGTH=$#ARRAY_VAR[*]
for (( i=0; i<=$(( $A_LENGTH -1 )); i++ )) ; do
echo ""
echo "INDEX - $i"
echo "VALUE - $ARRAY_VAR[$i]"
done
exit 0
[Ref.: https://tecadmin.net/working-with-array-bash-script/ ]
add a comment |
What I do is:
array="$(echo $array | tr ' ' 'n' | sed "/itemtodelete/d")"
BAM, that item is removed.
1
This breaks forarray=('first item' 'second item')
.
– Benjamin W.
Jun 14 '16 at 17:17
add a comment |
This is a quick-and-dirty solution that will work in simple cases but will break if (a) there are regex special characters in $delete
, or (b) there are any spaces at all in any items. Starting with:
array+=(pluto)
array+=(pippo)
delete=(pluto)
Delete all entries exactly matching $delete
:
array=(`echo $array | fmt -1 | grep -v "^$delete$" | fmt -999999`)
resulting inecho $array
-> pippo, and making sure it's an array:echo $array[1]
-> pippo
fmt
is a little obscure: fmt -1
wraps at the first column (to put each item on its own line. That's where the problem arises with items in spaces.) fmt -999999
unwraps it back to one line, putting back the spaces between items. There are other ways to do that, such as xargs
.
Addendum: If you want to delete just the first match, use sed, as described here:
array=(`echo $array | fmt -1 | sed "0,/^$delete$///d;" | fmt -999999`)
add a comment |
How about something like:
array=(one two three)
array_t=" $array[@] "
delete=one
array=($array_t// $delete / )
unset array_t
add a comment |
#/bin/bash
echo "# define array with six elements"
arr=(zero one two three 'four 4' five)
echo "# unset by index: 0"
unset -v 'arr[0]'
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
arr_delete_by_content() # value to delete
for i in $!arr[*]; do
[ "$arr[$i]" = "$1" ] && unset -v 'arr[$i]'
done
echo "# unset in global variable where value: three"
arr_delete_by_content three
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
echo "# rearrange indices"
arr=( "$arr[@]" )
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_value() sed 's,^[^=]*=,,'
echo "# new array without value: two"
declare -a arr="$(delete_value two "$arr[@]")"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_values() # arraydecl values..., returns array decl. (keeps indices)
declare -a arr="$1"; local i v; shift
for v in "$@"; do
for i in $!arr[*]; do
[ "$v" = "$arr[$i]" ] && unset -v 'arr[$i]'
done
done
declare -p arr
echo "# new array without values: one five (keep indices)"
declare -a arr="$(delete_values "$(declare -p arr|sed 's,^[^=]*=,,')" one five)"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
# new array without multiple values and rearranged indices is left to the reader
1
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
add a comment |
protected by codeforester Sep 15 '18 at 1:16
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
18 Answers
18
active
oldest
votes
18 Answers
18
active
oldest
votes
active
oldest
votes
active
oldest
votes
The following works as you would like in bash
and zsh
:
$ array=(pluto pippo)
$ delete=(pluto)
$ echo $array[@]/$delete
pippo
$ array=( "$array[@]/$delete" ) #Quotes when working with strings
If need to delete more than one element:
...
$ delete=(pluto pippo)
for del in $delete[@]
do
array=("$array[@]/$del") #Quotes when working with strings
done
Caveat
This technique actually removes prefixes matching $delete
from the elements, not necessarily whole elements.
Update
To really remove an exact item, you need to walk through the array, comparing the target to each element, and using unset
to delete an exact match.
array=(pluto pippo bob)
delete=(pippo)
for target in "$delete[@]"; do
for i in "$!array[@]"; do
if [[ $array[i] = "$delete[0]" ]]; then
unset 'array[i]'
fi
done
done
Note that if you do this, and one or more elements is removed, the indices will no longer be a continuous sequence of integers.
$ declare -p array
declare -a array=([0]="pluto" [2]="bob")
The simple fact is, arrays were not designed for use as mutable data structures. They are primarily used for storing lists of items in a single variable without needing to waste a character as a delimiter (e.g., to store a list of strings which can contain whitespace).
If gaps are a problem, then you need to rebuild the array to fill the gaps:
for i in "$!array[@]"; do
new_array+=( "$array[i]" )
done
array=("$new_array[@]")
unset new_array
31
just know that:$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results inflower
– bernstein
Mar 26 '14 at 14:41
9
Note that this is actually doing a substitution, so if the array is something like(pluto1 pluto2 pippo)
then you will end up with(1 2 pippo)
.
– haridsv
Sep 22 '14 at 5:22
2
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something likefor element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
2
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
3
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
|
show 9 more comments
The following works as you would like in bash
and zsh
:
$ array=(pluto pippo)
$ delete=(pluto)
$ echo $array[@]/$delete
pippo
$ array=( "$array[@]/$delete" ) #Quotes when working with strings
If need to delete more than one element:
...
$ delete=(pluto pippo)
for del in $delete[@]
do
array=("$array[@]/$del") #Quotes when working with strings
done
Caveat
This technique actually removes prefixes matching $delete
from the elements, not necessarily whole elements.
Update
To really remove an exact item, you need to walk through the array, comparing the target to each element, and using unset
to delete an exact match.
array=(pluto pippo bob)
delete=(pippo)
for target in "$delete[@]"; do
for i in "$!array[@]"; do
if [[ $array[i] = "$delete[0]" ]]; then
unset 'array[i]'
fi
done
done
Note that if you do this, and one or more elements is removed, the indices will no longer be a continuous sequence of integers.
$ declare -p array
declare -a array=([0]="pluto" [2]="bob")
The simple fact is, arrays were not designed for use as mutable data structures. They are primarily used for storing lists of items in a single variable without needing to waste a character as a delimiter (e.g., to store a list of strings which can contain whitespace).
If gaps are a problem, then you need to rebuild the array to fill the gaps:
for i in "$!array[@]"; do
new_array+=( "$array[i]" )
done
array=("$new_array[@]")
unset new_array
31
just know that:$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results inflower
– bernstein
Mar 26 '14 at 14:41
9
Note that this is actually doing a substitution, so if the array is something like(pluto1 pluto2 pippo)
then you will end up with(1 2 pippo)
.
– haridsv
Sep 22 '14 at 5:22
2
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something likefor element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
2
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
3
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
|
show 9 more comments
The following works as you would like in bash
and zsh
:
$ array=(pluto pippo)
$ delete=(pluto)
$ echo $array[@]/$delete
pippo
$ array=( "$array[@]/$delete" ) #Quotes when working with strings
If need to delete more than one element:
...
$ delete=(pluto pippo)
for del in $delete[@]
do
array=("$array[@]/$del") #Quotes when working with strings
done
Caveat
This technique actually removes prefixes matching $delete
from the elements, not necessarily whole elements.
Update
To really remove an exact item, you need to walk through the array, comparing the target to each element, and using unset
to delete an exact match.
array=(pluto pippo bob)
delete=(pippo)
for target in "$delete[@]"; do
for i in "$!array[@]"; do
if [[ $array[i] = "$delete[0]" ]]; then
unset 'array[i]'
fi
done
done
Note that if you do this, and one or more elements is removed, the indices will no longer be a continuous sequence of integers.
$ declare -p array
declare -a array=([0]="pluto" [2]="bob")
The simple fact is, arrays were not designed for use as mutable data structures. They are primarily used for storing lists of items in a single variable without needing to waste a character as a delimiter (e.g., to store a list of strings which can contain whitespace).
If gaps are a problem, then you need to rebuild the array to fill the gaps:
for i in "$!array[@]"; do
new_array+=( "$array[i]" )
done
array=("$new_array[@]")
unset new_array
The following works as you would like in bash
and zsh
:
$ array=(pluto pippo)
$ delete=(pluto)
$ echo $array[@]/$delete
pippo
$ array=( "$array[@]/$delete" ) #Quotes when working with strings
If need to delete more than one element:
...
$ delete=(pluto pippo)
for del in $delete[@]
do
array=("$array[@]/$del") #Quotes when working with strings
done
Caveat
This technique actually removes prefixes matching $delete
from the elements, not necessarily whole elements.
Update
To really remove an exact item, you need to walk through the array, comparing the target to each element, and using unset
to delete an exact match.
array=(pluto pippo bob)
delete=(pippo)
for target in "$delete[@]"; do
for i in "$!array[@]"; do
if [[ $array[i] = "$delete[0]" ]]; then
unset 'array[i]'
fi
done
done
Note that if you do this, and one or more elements is removed, the indices will no longer be a continuous sequence of integers.
$ declare -p array
declare -a array=([0]="pluto" [2]="bob")
The simple fact is, arrays were not designed for use as mutable data structures. They are primarily used for storing lists of items in a single variable without needing to waste a character as a delimiter (e.g., to store a list of strings which can contain whitespace).
If gaps are a problem, then you need to rebuild the array to fill the gaps:
for i in "$!array[@]"; do
new_array+=( "$array[i]" )
done
array=("$new_array[@]")
unset new_array
edited Dec 13 '17 at 10:39
muru
3,45718 silver badges56 bronze badges
3,45718 silver badges56 bronze badges
answered May 31 '13 at 16:33
chepnerchepner
280k40 gold badges275 silver badges370 bronze badges
280k40 gold badges275 silver badges370 bronze badges
31
just know that:$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results inflower
– bernstein
Mar 26 '14 at 14:41
9
Note that this is actually doing a substitution, so if the array is something like(pluto1 pluto2 pippo)
then you will end up with(1 2 pippo)
.
– haridsv
Sep 22 '14 at 5:22
2
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something likefor element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
2
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
3
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
|
show 9 more comments
31
just know that:$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results inflower
– bernstein
Mar 26 '14 at 14:41
9
Note that this is actually doing a substitution, so if the array is something like(pluto1 pluto2 pippo)
then you will end up with(1 2 pippo)
.
– haridsv
Sep 22 '14 at 5:22
2
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something likefor element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
2
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
3
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
31
31
just know that:
$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results in flower
– bernstein
Mar 26 '14 at 14:41
just know that:
$ array=(sun sunflower)
$ delete=(sun)
$ echo $array[@]/$delete
results in flower
– bernstein
Mar 26 '14 at 14:41
9
9
Note that this is actually doing a substitution, so if the array is something like
(pluto1 pluto2 pippo)
then you will end up with (1 2 pippo)
.– haridsv
Sep 22 '14 at 5:22
Note that this is actually doing a substitution, so if the array is something like
(pluto1 pluto2 pippo)
then you will end up with (1 2 pippo)
.– haridsv
Sep 22 '14 at 5:22
2
2
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something like
for element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
Just be careful using this in a for loop because you'll end up with an empty element where the deleted element was. For sanity you could do something like
for element in "$array[@]" do if [[ $element ]]; then echo $element fi done
– Joel B
Oct 21 '15 at 23:29
2
2
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
So how to delete only matching elements?
– UmaN
Feb 19 '16 at 9:09
3
3
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
Note: this may set the respective value to nothing, but the element will still be in the array.
– Blauhirn
Mar 26 '16 at 12:01
|
show 9 more comments
You could build up a new array without the undesired element, then assign it back to the old array. This works in bash
:
array=(pluto pippo)
new_array=()
for value in "$array[@]"
do
[[ $value != pluto ]] && new_array+=($value)
done
array=("$new_array[@]")
unset new_array
This yields:
echo "$array[@]"
pippo
add a comment |
You could build up a new array without the undesired element, then assign it back to the old array. This works in bash
:
array=(pluto pippo)
new_array=()
for value in "$array[@]"
do
[[ $value != pluto ]] && new_array+=($value)
done
array=("$new_array[@]")
unset new_array
This yields:
echo "$array[@]"
pippo
add a comment |
You could build up a new array without the undesired element, then assign it back to the old array. This works in bash
:
array=(pluto pippo)
new_array=()
for value in "$array[@]"
do
[[ $value != pluto ]] && new_array+=($value)
done
array=("$new_array[@]")
unset new_array
This yields:
echo "$array[@]"
pippo
You could build up a new array without the undesired element, then assign it back to the old array. This works in bash
:
array=(pluto pippo)
new_array=()
for value in "$array[@]"
do
[[ $value != pluto ]] && new_array+=($value)
done
array=("$new_array[@]")
unset new_array
This yields:
echo "$array[@]"
pippo
answered Jun 29 '15 at 18:21
Steve KehletSteve Kehlet
4,3823 gold badges26 silver badges34 bronze badges
4,3823 gold badges26 silver badges34 bronze badges
add a comment |
add a comment |
This is the most direct way to unset a value if you know it's position.
$ array=(one two three)
$ echo $#array[@]
3
$ unset 'array[1]'
$ echo $array[@]
one three
$ echo $#array[@]
2
3
Tryecho $array[1]
, you will get null string. And to getthree
you need to doecho $array[2]
. Sounset
is not the right mechanism to remove an element in bash array.
– rashok
Apr 3 '18 at 9:23
add a comment |
This is the most direct way to unset a value if you know it's position.
$ array=(one two three)
$ echo $#array[@]
3
$ unset 'array[1]'
$ echo $array[@]
one three
$ echo $#array[@]
2
3
Tryecho $array[1]
, you will get null string. And to getthree
you need to doecho $array[2]
. Sounset
is not the right mechanism to remove an element in bash array.
– rashok
Apr 3 '18 at 9:23
add a comment |
This is the most direct way to unset a value if you know it's position.
$ array=(one two three)
$ echo $#array[@]
3
$ unset 'array[1]'
$ echo $array[@]
one three
$ echo $#array[@]
2
This is the most direct way to unset a value if you know it's position.
$ array=(one two three)
$ echo $#array[@]
3
$ unset 'array[1]'
$ echo $array[@]
one three
$ echo $#array[@]
2
answered Dec 13 '17 at 17:05
signullsignull
711 silver badge1 bronze badge
711 silver badge1 bronze badge
3
Tryecho $array[1]
, you will get null string. And to getthree
you need to doecho $array[2]
. Sounset
is not the right mechanism to remove an element in bash array.
– rashok
Apr 3 '18 at 9:23
add a comment |
3
Tryecho $array[1]
, you will get null string. And to getthree
you need to doecho $array[2]
. Sounset
is not the right mechanism to remove an element in bash array.
– rashok
Apr 3 '18 at 9:23
3
3
Try
echo $array[1]
, you will get null string. And to get three
you need to do echo $array[2]
. So unset
is not the right mechanism to remove an element in bash array.– rashok
Apr 3 '18 at 9:23
Try
echo $array[1]
, you will get null string. And to get three
you need to do echo $array[2]
. So unset
is not the right mechanism to remove an element in bash array.– rashok
Apr 3 '18 at 9:23
add a comment |
Here's a one-line solution with mapfile:
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "<regexp>")
Example:
$ arr=("Adam" "Bob" "Claire"$'n'"Smith" "David" "Eve" "Fred")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 6 Contents: Adam Bob Claire
Smith David Eve Fred
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "^ClairenSmith$")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 5 Contents: Adam Bob David Eve Fred
This method allows for great flexibility by modifying/exchanging the grep command and doesn't leave any empty strings in the array.
1
Please useprintf '%sn' "$array[@]"
instead of that uglyIFS
/echo
thing.
– gniourf_gniourf
Jan 15 '17 at 19:07
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
@Socowi You're incorrect, at least on bash 4.4.19.-d $''
works perfectly fine while just-d
without the argument does not.
– Niklas Holm
Mar 27 at 9:13
Ah yes, I mixed it up. Sorry. What I meant was:-d $''
is the same as-d $' something'
or just-d ''
.
– Socowi
Mar 27 at 9:27
|
show 1 more comment
Here's a one-line solution with mapfile:
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "<regexp>")
Example:
$ arr=("Adam" "Bob" "Claire"$'n'"Smith" "David" "Eve" "Fred")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 6 Contents: Adam Bob Claire
Smith David Eve Fred
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "^ClairenSmith$")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 5 Contents: Adam Bob David Eve Fred
This method allows for great flexibility by modifying/exchanging the grep command and doesn't leave any empty strings in the array.
1
Please useprintf '%sn' "$array[@]"
instead of that uglyIFS
/echo
thing.
– gniourf_gniourf
Jan 15 '17 at 19:07
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
@Socowi You're incorrect, at least on bash 4.4.19.-d $''
works perfectly fine while just-d
without the argument does not.
– Niklas Holm
Mar 27 at 9:13
Ah yes, I mixed it up. Sorry. What I meant was:-d $''
is the same as-d $' something'
or just-d ''
.
– Socowi
Mar 27 at 9:27
|
show 1 more comment
Here's a one-line solution with mapfile:
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "<regexp>")
Example:
$ arr=("Adam" "Bob" "Claire"$'n'"Smith" "David" "Eve" "Fred")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 6 Contents: Adam Bob Claire
Smith David Eve Fred
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "^ClairenSmith$")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 5 Contents: Adam Bob David Eve Fred
This method allows for great flexibility by modifying/exchanging the grep command and doesn't leave any empty strings in the array.
Here's a one-line solution with mapfile:
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "<regexp>")
Example:
$ arr=("Adam" "Bob" "Claire"$'n'"Smith" "David" "Eve" "Fred")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 6 Contents: Adam Bob Claire
Smith David Eve Fred
$ mapfile -d $'' -t arr < <(printf '%s' "$arr[@]" | grep -Pzv "^ClairenSmith$")
$ echo "Size: $#arr[*] Contents: $arr[*]"
Size: 5 Contents: Adam Bob David Eve Fred
This method allows for great flexibility by modifying/exchanging the grep command and doesn't leave any empty strings in the array.
edited Mar 23 '18 at 8:26
answered Oct 26 '16 at 13:46
Niklas HolmNiklas Holm
3452 silver badges9 bronze badges
3452 silver badges9 bronze badges
1
Please useprintf '%sn' "$array[@]"
instead of that uglyIFS
/echo
thing.
– gniourf_gniourf
Jan 15 '17 at 19:07
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
@Socowi You're incorrect, at least on bash 4.4.19.-d $''
works perfectly fine while just-d
without the argument does not.
– Niklas Holm
Mar 27 at 9:13
Ah yes, I mixed it up. Sorry. What I meant was:-d $''
is the same as-d $' something'
or just-d ''
.
– Socowi
Mar 27 at 9:27
|
show 1 more comment
1
Please useprintf '%sn' "$array[@]"
instead of that uglyIFS
/echo
thing.
– gniourf_gniourf
Jan 15 '17 at 19:07
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
@Socowi You're incorrect, at least on bash 4.4.19.-d $''
works perfectly fine while just-d
without the argument does not.
– Niklas Holm
Mar 27 at 9:13
Ah yes, I mixed it up. Sorry. What I meant was:-d $''
is the same as-d $' something'
or just-d ''
.
– Socowi
Mar 27 at 9:27
1
1
Please use
printf '%sn' "$array[@]"
instead of that ugly IFS
/echo
thing.– gniourf_gniourf
Jan 15 '17 at 19:07
Please use
printf '%sn' "$array[@]"
instead of that ugly IFS
/echo
thing.– gniourf_gniourf
Jan 15 '17 at 19:07
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
Note that this fails with fields that contain newlines.
– gniourf_gniourf
Jan 15 '17 at 19:08
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
I've edited the answer to allow newlines in fields.
– Niklas Holm
Mar 23 '18 at 8:14
@Socowi You're incorrect, at least on bash 4.4.19.
-d $''
works perfectly fine while just -d
without the argument does not.– Niklas Holm
Mar 27 at 9:13
@Socowi You're incorrect, at least on bash 4.4.19.
-d $''
works perfectly fine while just -d
without the argument does not.– Niklas Holm
Mar 27 at 9:13
Ah yes, I mixed it up. Sorry. What I meant was:
-d $''
is the same as-d $' something'
or just -d ''
.– Socowi
Mar 27 at 9:27
Ah yes, I mixed it up. Sorry. What I meant was:
-d $''
is the same as-d $' something'
or just -d ''
.– Socowi
Mar 27 at 9:27
|
show 1 more comment
To expand on the above answers, the following can be used to remove multiple elements from an array, without partial matching:
ARRAY=(one two onetwo three four threefour "one six")
TO_REMOVE=(one four)
TEMP_ARRAY=()
for pkg in "$ARRAY[@]"; do
for remove in "$TO_REMOVE[@]"; do
KEEP=true
if [[ $pkg == $remove ]]; then
KEEP=false
break
fi
done
if $KEEP; then
TEMP_ARRAY+=($pkg)
fi
done
ARRAY=("$TEMP_ARRAY[@]")
unset TEMP_ARRAY
This will result in an array containing:
(two onetwo three threefour "one six")
add a comment |
To expand on the above answers, the following can be used to remove multiple elements from an array, without partial matching:
ARRAY=(one two onetwo three four threefour "one six")
TO_REMOVE=(one four)
TEMP_ARRAY=()
for pkg in "$ARRAY[@]"; do
for remove in "$TO_REMOVE[@]"; do
KEEP=true
if [[ $pkg == $remove ]]; then
KEEP=false
break
fi
done
if $KEEP; then
TEMP_ARRAY+=($pkg)
fi
done
ARRAY=("$TEMP_ARRAY[@]")
unset TEMP_ARRAY
This will result in an array containing:
(two onetwo three threefour "one six")
add a comment |
To expand on the above answers, the following can be used to remove multiple elements from an array, without partial matching:
ARRAY=(one two onetwo three four threefour "one six")
TO_REMOVE=(one four)
TEMP_ARRAY=()
for pkg in "$ARRAY[@]"; do
for remove in "$TO_REMOVE[@]"; do
KEEP=true
if [[ $pkg == $remove ]]; then
KEEP=false
break
fi
done
if $KEEP; then
TEMP_ARRAY+=($pkg)
fi
done
ARRAY=("$TEMP_ARRAY[@]")
unset TEMP_ARRAY
This will result in an array containing:
(two onetwo three threefour "one six")
To expand on the above answers, the following can be used to remove multiple elements from an array, without partial matching:
ARRAY=(one two onetwo three four threefour "one six")
TO_REMOVE=(one four)
TEMP_ARRAY=()
for pkg in "$ARRAY[@]"; do
for remove in "$TO_REMOVE[@]"; do
KEEP=true
if [[ $pkg == $remove ]]; then
KEEP=false
break
fi
done
if $KEEP; then
TEMP_ARRAY+=($pkg)
fi
done
ARRAY=("$TEMP_ARRAY[@]")
unset TEMP_ARRAY
This will result in an array containing:
(two onetwo three threefour "one six")
answered Mar 16 '16 at 9:48
DylanDylan
3512 silver badges6 bronze badges
3512 silver badges6 bronze badges
add a comment |
add a comment |
Here's a (probably very bash-specific) little function involving bash variable indirection and unset
; it's a general solution that does not involve text substitution or discarding empty elements and has no problems with quoting/whitespace etc.
delete_ary_elmt()
local word=$1 # the element to search for & delete
local aryref="$2[@]" # a necessary step since '$!$2[@]' is a syntax error
local arycopy=("$!aryref") # create a copy of the input array
local status=1
for (( i = $#arycopy[@] - 1; i >= 0; i-- )); do # iterate over indices backwards
elmt=$arycopy[$i]
[[ $elmt == $word ]] && unset "$2[$i]" && status=0 # unset matching elmts in orig. ary
done
return $status # return 0 if something was deleted; 1 if not
array=(a 0 0 b 0 0 0 c 0 d e 0 0 0)
delete_ary_elmt 0 array
for e in "$array[@]"; do
echo "$e"
done
# prints "a" "b" "c" "d" in lines
Use it like delete_ary_elmt ELEMENT ARRAYNAME
without any $
sigil. Switch the == $word
for == $word*
for prefix matches; use $elmt,, == $word,,
for case-insensitive matches; etc., whatever bash [[
supports.
It works by determining the indices of the input array and iterating over them backwards (so deleting elements doesn't screw up iteration order). To get the indices you need to access the input array by name, which can be done via bash variable indirection x=1; varname=x; echo $!varname # prints "1"
.
You can't access arrays by name like aryname=a; echo "$$aryname[@]
, this gives you an error. You can't do aryname=a; echo "$!aryname[@]"
, this gives you the indices of the variable aryname
(although it is not an array). What DOES work is aryref="a[@]"; echo "$!aryref"
, which will print the elements of the array a
, preserving shell-word quoting and whitespace exactly like echo "$a[@]"
. But this only works for printing the elements of an array, not for printing its length or indices (aryref="!a[@]"
or aryref="#a[@]"
or "$!!aryref"
or "$#!aryref"
, they all fail).
So I copy the original array by its name via bash indirection and get the indices from the copy. To iterate over the indices in reverse I use a C-style for loop. I could also do it by accessing the indices via $!arycopy[@]
and reversing them with tac
, which is a cat
that turns around the input line order.
A function solution without variable indirection would probably have to involve eval
, which may or may not be safe to use in that situation (I can't tell).
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try runningdelete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.
– Scott
Feb 26 '18 at 19:26
add a comment |
Here's a (probably very bash-specific) little function involving bash variable indirection and unset
; it's a general solution that does not involve text substitution or discarding empty elements and has no problems with quoting/whitespace etc.
delete_ary_elmt()
local word=$1 # the element to search for & delete
local aryref="$2[@]" # a necessary step since '$!$2[@]' is a syntax error
local arycopy=("$!aryref") # create a copy of the input array
local status=1
for (( i = $#arycopy[@] - 1; i >= 0; i-- )); do # iterate over indices backwards
elmt=$arycopy[$i]
[[ $elmt == $word ]] && unset "$2[$i]" && status=0 # unset matching elmts in orig. ary
done
return $status # return 0 if something was deleted; 1 if not
array=(a 0 0 b 0 0 0 c 0 d e 0 0 0)
delete_ary_elmt 0 array
for e in "$array[@]"; do
echo "$e"
done
# prints "a" "b" "c" "d" in lines
Use it like delete_ary_elmt ELEMENT ARRAYNAME
without any $
sigil. Switch the == $word
for == $word*
for prefix matches; use $elmt,, == $word,,
for case-insensitive matches; etc., whatever bash [[
supports.
It works by determining the indices of the input array and iterating over them backwards (so deleting elements doesn't screw up iteration order). To get the indices you need to access the input array by name, which can be done via bash variable indirection x=1; varname=x; echo $!varname # prints "1"
.
You can't access arrays by name like aryname=a; echo "$$aryname[@]
, this gives you an error. You can't do aryname=a; echo "$!aryname[@]"
, this gives you the indices of the variable aryname
(although it is not an array). What DOES work is aryref="a[@]"; echo "$!aryref"
, which will print the elements of the array a
, preserving shell-word quoting and whitespace exactly like echo "$a[@]"
. But this only works for printing the elements of an array, not for printing its length or indices (aryref="!a[@]"
or aryref="#a[@]"
or "$!!aryref"
or "$#!aryref"
, they all fail).
So I copy the original array by its name via bash indirection and get the indices from the copy. To iterate over the indices in reverse I use a C-style for loop. I could also do it by accessing the indices via $!arycopy[@]
and reversing them with tac
, which is a cat
that turns around the input line order.
A function solution without variable indirection would probably have to involve eval
, which may or may not be safe to use in that situation (I can't tell).
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try runningdelete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.
– Scott
Feb 26 '18 at 19:26
add a comment |
Here's a (probably very bash-specific) little function involving bash variable indirection and unset
; it's a general solution that does not involve text substitution or discarding empty elements and has no problems with quoting/whitespace etc.
delete_ary_elmt()
local word=$1 # the element to search for & delete
local aryref="$2[@]" # a necessary step since '$!$2[@]' is a syntax error
local arycopy=("$!aryref") # create a copy of the input array
local status=1
for (( i = $#arycopy[@] - 1; i >= 0; i-- )); do # iterate over indices backwards
elmt=$arycopy[$i]
[[ $elmt == $word ]] && unset "$2[$i]" && status=0 # unset matching elmts in orig. ary
done
return $status # return 0 if something was deleted; 1 if not
array=(a 0 0 b 0 0 0 c 0 d e 0 0 0)
delete_ary_elmt 0 array
for e in "$array[@]"; do
echo "$e"
done
# prints "a" "b" "c" "d" in lines
Use it like delete_ary_elmt ELEMENT ARRAYNAME
without any $
sigil. Switch the == $word
for == $word*
for prefix matches; use $elmt,, == $word,,
for case-insensitive matches; etc., whatever bash [[
supports.
It works by determining the indices of the input array and iterating over them backwards (so deleting elements doesn't screw up iteration order). To get the indices you need to access the input array by name, which can be done via bash variable indirection x=1; varname=x; echo $!varname # prints "1"
.
You can't access arrays by name like aryname=a; echo "$$aryname[@]
, this gives you an error. You can't do aryname=a; echo "$!aryname[@]"
, this gives you the indices of the variable aryname
(although it is not an array). What DOES work is aryref="a[@]"; echo "$!aryref"
, which will print the elements of the array a
, preserving shell-word quoting and whitespace exactly like echo "$a[@]"
. But this only works for printing the elements of an array, not for printing its length or indices (aryref="!a[@]"
or aryref="#a[@]"
or "$!!aryref"
or "$#!aryref"
, they all fail).
So I copy the original array by its name via bash indirection and get the indices from the copy. To iterate over the indices in reverse I use a C-style for loop. I could also do it by accessing the indices via $!arycopy[@]
and reversing them with tac
, which is a cat
that turns around the input line order.
A function solution without variable indirection would probably have to involve eval
, which may or may not be safe to use in that situation (I can't tell).
Here's a (probably very bash-specific) little function involving bash variable indirection and unset
; it's a general solution that does not involve text substitution or discarding empty elements and has no problems with quoting/whitespace etc.
delete_ary_elmt()
local word=$1 # the element to search for & delete
local aryref="$2[@]" # a necessary step since '$!$2[@]' is a syntax error
local arycopy=("$!aryref") # create a copy of the input array
local status=1
for (( i = $#arycopy[@] - 1; i >= 0; i-- )); do # iterate over indices backwards
elmt=$arycopy[$i]
[[ $elmt == $word ]] && unset "$2[$i]" && status=0 # unset matching elmts in orig. ary
done
return $status # return 0 if something was deleted; 1 if not
array=(a 0 0 b 0 0 0 c 0 d e 0 0 0)
delete_ary_elmt 0 array
for e in "$array[@]"; do
echo "$e"
done
# prints "a" "b" "c" "d" in lines
Use it like delete_ary_elmt ELEMENT ARRAYNAME
without any $
sigil. Switch the == $word
for == $word*
for prefix matches; use $elmt,, == $word,,
for case-insensitive matches; etc., whatever bash [[
supports.
It works by determining the indices of the input array and iterating over them backwards (so deleting elements doesn't screw up iteration order). To get the indices you need to access the input array by name, which can be done via bash variable indirection x=1; varname=x; echo $!varname # prints "1"
.
You can't access arrays by name like aryname=a; echo "$$aryname[@]
, this gives you an error. You can't do aryname=a; echo "$!aryname[@]"
, this gives you the indices of the variable aryname
(although it is not an array). What DOES work is aryref="a[@]"; echo "$!aryref"
, which will print the elements of the array a
, preserving shell-word quoting and whitespace exactly like echo "$a[@]"
. But this only works for printing the elements of an array, not for printing its length or indices (aryref="!a[@]"
or aryref="#a[@]"
or "$!!aryref"
or "$#!aryref"
, they all fail).
So I copy the original array by its name via bash indirection and get the indices from the copy. To iterate over the indices in reverse I use a C-style for loop. I could also do it by accessing the indices via $!arycopy[@]
and reversing them with tac
, which is a cat
that turns around the input line order.
A function solution without variable indirection would probably have to involve eval
, which may or may not be safe to use in that situation (I can't tell).
answered Jan 15 '17 at 18:17
S.V.P.S.V.P.
211 bronze badge
211 bronze badge
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try runningdelete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.
– Scott
Feb 26 '18 at 19:26
add a comment |
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try runningdelete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.
– Scott
Feb 26 '18 at 19:26
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try running
delete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.– Scott
Feb 26 '18 at 19:26
This almost works nicely, however it doesn't redeclare the initial array passed into the function, so while that initial array has its values missing, it also has its indexes messed up. What this mean is that the next call you make to delete_ary_elmt on the same array will not work (or will remove the wrong things). For instance, after what you have pasted, try running
delete_ary_elmt "d" array
and then re-printing the array. You will see that the wrong element gets removed. Removing the last element will also then never work.– Scott
Feb 26 '18 at 19:26
add a comment |
Using unset
To remove an element at particular index, we can use unset
and then do copy to another array. Only just unset
is not required in this case. Because unset
does not remove the element it just sets null string to the particular index in array.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in "$arr[@]"
do
arr2[$i]=$element
((++i))
done
echo "$arr[@]"
echo "1st val is $arr[1], 2nd val is $arr[2]"
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd
Using :<idx>
We can remove some set of elements using :<idx>
also. For example if we want to remove 1st element we can use :1
as mentioned below.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
arr2=("$arr[@]:1")
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
bb cc dd ee
1st val is cc, 2nd val is dd
add a comment |
Using unset
To remove an element at particular index, we can use unset
and then do copy to another array. Only just unset
is not required in this case. Because unset
does not remove the element it just sets null string to the particular index in array.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in "$arr[@]"
do
arr2[$i]=$element
((++i))
done
echo "$arr[@]"
echo "1st val is $arr[1], 2nd val is $arr[2]"
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd
Using :<idx>
We can remove some set of elements using :<idx>
also. For example if we want to remove 1st element we can use :1
as mentioned below.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
arr2=("$arr[@]:1")
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
bb cc dd ee
1st val is cc, 2nd val is dd
add a comment |
Using unset
To remove an element at particular index, we can use unset
and then do copy to another array. Only just unset
is not required in this case. Because unset
does not remove the element it just sets null string to the particular index in array.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in "$arr[@]"
do
arr2[$i]=$element
((++i))
done
echo "$arr[@]"
echo "1st val is $arr[1], 2nd val is $arr[2]"
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd
Using :<idx>
We can remove some set of elements using :<idx>
also. For example if we want to remove 1st element we can use :1
as mentioned below.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
arr2=("$arr[@]:1")
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
bb cc dd ee
1st val is cc, 2nd val is dd
Using unset
To remove an element at particular index, we can use unset
and then do copy to another array. Only just unset
is not required in this case. Because unset
does not remove the element it just sets null string to the particular index in array.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in "$arr[@]"
do
arr2[$i]=$element
((++i))
done
echo "$arr[@]"
echo "1st val is $arr[1], 2nd val is $arr[2]"
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd
Using :<idx>
We can remove some set of elements using :<idx>
also. For example if we want to remove 1st element we can use :1
as mentioned below.
declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
arr2=("$arr[@]:1")
echo "$arr2[@]"
echo "1st val is $arr2[1], 2nd val is $arr2[2]"
Output is
bb cc dd ee
1st val is cc, 2nd val is dd
edited Jan 25 at 17:16
gniourf_gniourf
32.3k5 gold badges69 silver badges84 bronze badges
32.3k5 gold badges69 silver badges84 bronze badges
answered Apr 3 '18 at 9:43
rashokrashok
6,55811 gold badges57 silver badges79 bronze badges
6,55811 gold badges57 silver badges79 bronze badges
add a comment |
add a comment |
POSIX shell script does not have arrays.
So most probably you are using a specific dialect such as bash
, korn shells or zsh
.
Therefore, your question as of now cannot be answered.
Maybe this works for you:
unset array[$delete]
2
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
add a comment |
POSIX shell script does not have arrays.
So most probably you are using a specific dialect such as bash
, korn shells or zsh
.
Therefore, your question as of now cannot be answered.
Maybe this works for you:
unset array[$delete]
2
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
add a comment |
POSIX shell script does not have arrays.
So most probably you are using a specific dialect such as bash
, korn shells or zsh
.
Therefore, your question as of now cannot be answered.
Maybe this works for you:
unset array[$delete]
POSIX shell script does not have arrays.
So most probably you are using a specific dialect such as bash
, korn shells or zsh
.
Therefore, your question as of now cannot be answered.
Maybe this works for you:
unset array[$delete]
answered May 31 '13 at 15:38
Anony-MousseAnony-Mousse
61.3k8 gold badges100 silver badges166 bronze badges
61.3k8 gold badges100 silver badges166 bronze badges
2
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
add a comment |
2
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
2
2
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
Hi, I'm using bash shell atm. And "$delete" is not the position of the element but the string itself. So I don't think "unset" will work
– Alex
May 31 '13 at 16:07
add a comment |
Actually, I just noticed that the shell syntax somewhat has a behavior built-in that allows for easy reconstruction of the array when, as posed in the question, an item should be removed.
# let's set up an array of items to consume:
x=()
for (( i=0; i<10; i++ )); do
x+=("$i")
done
# here, we consume that array:
while (( $#x[@] )); do
i=$(( $RANDOM % $#x[@] ))
echo "$x[i] / $x[@]"
x=("$x[@]:0:i" "$x[@]:i+1")
done
Notice how we constructed the array using bash's x+=()
syntax?
You could actually add more than one item with that, the content of a whole other array at once.
add a comment |
Actually, I just noticed that the shell syntax somewhat has a behavior built-in that allows for easy reconstruction of the array when, as posed in the question, an item should be removed.
# let's set up an array of items to consume:
x=()
for (( i=0; i<10; i++ )); do
x+=("$i")
done
# here, we consume that array:
while (( $#x[@] )); do
i=$(( $RANDOM % $#x[@] ))
echo "$x[i] / $x[@]"
x=("$x[@]:0:i" "$x[@]:i+1")
done
Notice how we constructed the array using bash's x+=()
syntax?
You could actually add more than one item with that, the content of a whole other array at once.
add a comment |
Actually, I just noticed that the shell syntax somewhat has a behavior built-in that allows for easy reconstruction of the array when, as posed in the question, an item should be removed.
# let's set up an array of items to consume:
x=()
for (( i=0; i<10; i++ )); do
x+=("$i")
done
# here, we consume that array:
while (( $#x[@] )); do
i=$(( $RANDOM % $#x[@] ))
echo "$x[i] / $x[@]"
x=("$x[@]:0:i" "$x[@]:i+1")
done
Notice how we constructed the array using bash's x+=()
syntax?
You could actually add more than one item with that, the content of a whole other array at once.
Actually, I just noticed that the shell syntax somewhat has a behavior built-in that allows for easy reconstruction of the array when, as posed in the question, an item should be removed.
# let's set up an array of items to consume:
x=()
for (( i=0; i<10; i++ )); do
x+=("$i")
done
# here, we consume that array:
while (( $#x[@] )); do
i=$(( $RANDOM % $#x[@] ))
echo "$x[i] / $x[@]"
x=("$x[@]:0:i" "$x[@]:i+1")
done
Notice how we constructed the array using bash's x+=()
syntax?
You could actually add more than one item with that, the content of a whole other array at once.
edited Dec 21 '16 at 7:25
answered Dec 21 '16 at 7:20
mar77imar77i
826 bronze badges
826 bronze badges
add a comment |
add a comment |
http://wiki.bash-hackers.org/syntax/pe#substring_removal
$PARAMETER#PATTERN # remove from beginning
$PARAMETER##PATTERN # remove from the beginning, greedy match
$PARAMETER%PATTERN # remove from the end
$PARAMETER%%PATTERN # remove from the end, greedy match
In order to do a full remove element, you have to do an unset command with an if statement. If you don't care about removing prefixes from other variables or about supporting whitespace in the array, then you can just drop the quotes and forget about for loops.
See example below for a few different ways to clean up an array.
options=("foo" "bar" "foo" "foobar" "foo bar" "bars" "bar")
# remove bar from the start of each element
options=("$options[@]/#"bar"")
# options=("foo" "" "foo" "foobar" "foo bar" "s" "")
# remove the complete string "foo" in a for loop
count=$#options[@]
for ((i = 0; i < count; i++)); do
if [ "$options[i]" = "foo" ] ; then
unset 'options[i]'
fi
done
# options=( "" "foobar" "foo bar" "s" "")
# remove empty options
# note the count variable can't be recalculated easily on a sparse array
for ((i = 0; i < count; i++)); do
# echo "Element $i: '$options[i]'"
if [ -z "$options[i]" ] ; then
unset 'options[i]'
fi
done
# options=("foobar" "foo bar" "s")
# list them with select
echo "Choose an option:"
PS3='Option? '
select i in "$options[@]" Quit
do
case $i in
Quit) break ;;
*) echo "You selected "$i"" ;;
esac
done
Output
Choose an option:
1) foobar
2) foo bar
3) s
4) Quit
Option?
Hope that helps.
add a comment |
http://wiki.bash-hackers.org/syntax/pe#substring_removal
$PARAMETER#PATTERN # remove from beginning
$PARAMETER##PATTERN # remove from the beginning, greedy match
$PARAMETER%PATTERN # remove from the end
$PARAMETER%%PATTERN # remove from the end, greedy match
In order to do a full remove element, you have to do an unset command with an if statement. If you don't care about removing prefixes from other variables or about supporting whitespace in the array, then you can just drop the quotes and forget about for loops.
See example below for a few different ways to clean up an array.
options=("foo" "bar" "foo" "foobar" "foo bar" "bars" "bar")
# remove bar from the start of each element
options=("$options[@]/#"bar"")
# options=("foo" "" "foo" "foobar" "foo bar" "s" "")
# remove the complete string "foo" in a for loop
count=$#options[@]
for ((i = 0; i < count; i++)); do
if [ "$options[i]" = "foo" ] ; then
unset 'options[i]'
fi
done
# options=( "" "foobar" "foo bar" "s" "")
# remove empty options
# note the count variable can't be recalculated easily on a sparse array
for ((i = 0; i < count; i++)); do
# echo "Element $i: '$options[i]'"
if [ -z "$options[i]" ] ; then
unset 'options[i]'
fi
done
# options=("foobar" "foo bar" "s")
# list them with select
echo "Choose an option:"
PS3='Option? '
select i in "$options[@]" Quit
do
case $i in
Quit) break ;;
*) echo "You selected "$i"" ;;
esac
done
Output
Choose an option:
1) foobar
2) foo bar
3) s
4) Quit
Option?
Hope that helps.
add a comment |
http://wiki.bash-hackers.org/syntax/pe#substring_removal
$PARAMETER#PATTERN # remove from beginning
$PARAMETER##PATTERN # remove from the beginning, greedy match
$PARAMETER%PATTERN # remove from the end
$PARAMETER%%PATTERN # remove from the end, greedy match
In order to do a full remove element, you have to do an unset command with an if statement. If you don't care about removing prefixes from other variables or about supporting whitespace in the array, then you can just drop the quotes and forget about for loops.
See example below for a few different ways to clean up an array.
options=("foo" "bar" "foo" "foobar" "foo bar" "bars" "bar")
# remove bar from the start of each element
options=("$options[@]/#"bar"")
# options=("foo" "" "foo" "foobar" "foo bar" "s" "")
# remove the complete string "foo" in a for loop
count=$#options[@]
for ((i = 0; i < count; i++)); do
if [ "$options[i]" = "foo" ] ; then
unset 'options[i]'
fi
done
# options=( "" "foobar" "foo bar" "s" "")
# remove empty options
# note the count variable can't be recalculated easily on a sparse array
for ((i = 0; i < count; i++)); do
# echo "Element $i: '$options[i]'"
if [ -z "$options[i]" ] ; then
unset 'options[i]'
fi
done
# options=("foobar" "foo bar" "s")
# list them with select
echo "Choose an option:"
PS3='Option? '
select i in "$options[@]" Quit
do
case $i in
Quit) break ;;
*) echo "You selected "$i"" ;;
esac
done
Output
Choose an option:
1) foobar
2) foo bar
3) s
4) Quit
Option?
Hope that helps.
http://wiki.bash-hackers.org/syntax/pe#substring_removal
$PARAMETER#PATTERN # remove from beginning
$PARAMETER##PATTERN # remove from the beginning, greedy match
$PARAMETER%PATTERN # remove from the end
$PARAMETER%%PATTERN # remove from the end, greedy match
In order to do a full remove element, you have to do an unset command with an if statement. If you don't care about removing prefixes from other variables or about supporting whitespace in the array, then you can just drop the quotes and forget about for loops.
See example below for a few different ways to clean up an array.
options=("foo" "bar" "foo" "foobar" "foo bar" "bars" "bar")
# remove bar from the start of each element
options=("$options[@]/#"bar"")
# options=("foo" "" "foo" "foobar" "foo bar" "s" "")
# remove the complete string "foo" in a for loop
count=$#options[@]
for ((i = 0; i < count; i++)); do
if [ "$options[i]" = "foo" ] ; then
unset 'options[i]'
fi
done
# options=( "" "foobar" "foo bar" "s" "")
# remove empty options
# note the count variable can't be recalculated easily on a sparse array
for ((i = 0; i < count; i++)); do
# echo "Element $i: '$options[i]'"
if [ -z "$options[i]" ] ; then
unset 'options[i]'
fi
done
# options=("foobar" "foo bar" "s")
# list them with select
echo "Choose an option:"
PS3='Option? '
select i in "$options[@]" Quit
do
case $i in
Quit) break ;;
*) echo "You selected "$i"" ;;
esac
done
Output
Choose an option:
1) foobar
2) foo bar
3) s
4) Quit
Option?
Hope that helps.
edited Jan 15 '17 at 19:05
gniourf_gniourf
32.3k5 gold badges69 silver badges84 bronze badges
32.3k5 gold badges69 silver badges84 bronze badges
answered Nov 16 '16 at 20:47
phyattphyatt
14.8k2 gold badges35 silver badges54 bronze badges
14.8k2 gold badges35 silver badges54 bronze badges
add a comment |
add a comment |
In ZSH this is dead easy (note this uses more bash compatible syntax than necessary where possible for ease of understanding):
# I always include an edge case to make sure each element
# is not being word split.
start=(one two three 'four 4' five)
work=($(@)start)
idx=2
val=$work[idx]
# How to remove a single element easily.
# Also works for associative arrays (at least in zsh)
work[$idx]=()
echo "Array size went down by one: "
[[ $#work -eq $(($#start - 1)) ]] && echo "OK"
echo "Array item "$val" is now gone: "
[[ -z $work[(r)$val] ]] && echo OK
echo "Array contents are as expected: "
wanted=("$start[@]:0:1" "$start[@]:2")
[[ "$(j.:.)wanted[@]" == "$(j.:.)work[@]" ]] && echo "OK"
echo "-- array contents: start --"
print -l -r -- "-- $#start elements" $(@)start
echo "-- array contents: work --"
print -l -r -- "-- $#work elements" "$work[@]"
Results:
Array size went down by one:
OK
Array item two is now gone:
OK
Array contents are as expected:
OK
-- array contents: start --
-- 5 elements
one
two
three
four 4
five
-- array contents: work --
-- 4 elements
one
three
four 4
five
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
add a comment |
In ZSH this is dead easy (note this uses more bash compatible syntax than necessary where possible for ease of understanding):
# I always include an edge case to make sure each element
# is not being word split.
start=(one two three 'four 4' five)
work=($(@)start)
idx=2
val=$work[idx]
# How to remove a single element easily.
# Also works for associative arrays (at least in zsh)
work[$idx]=()
echo "Array size went down by one: "
[[ $#work -eq $(($#start - 1)) ]] && echo "OK"
echo "Array item "$val" is now gone: "
[[ -z $work[(r)$val] ]] && echo OK
echo "Array contents are as expected: "
wanted=("$start[@]:0:1" "$start[@]:2")
[[ "$(j.:.)wanted[@]" == "$(j.:.)work[@]" ]] && echo "OK"
echo "-- array contents: start --"
print -l -r -- "-- $#start elements" $(@)start
echo "-- array contents: work --"
print -l -r -- "-- $#work elements" "$work[@]"
Results:
Array size went down by one:
OK
Array item two is now gone:
OK
Array contents are as expected:
OK
-- array contents: start --
-- 5 elements
one
two
three
four 4
five
-- array contents: work --
-- 4 elements
one
three
four 4
five
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
add a comment |
In ZSH this is dead easy (note this uses more bash compatible syntax than necessary where possible for ease of understanding):
# I always include an edge case to make sure each element
# is not being word split.
start=(one two three 'four 4' five)
work=($(@)start)
idx=2
val=$work[idx]
# How to remove a single element easily.
# Also works for associative arrays (at least in zsh)
work[$idx]=()
echo "Array size went down by one: "
[[ $#work -eq $(($#start - 1)) ]] && echo "OK"
echo "Array item "$val" is now gone: "
[[ -z $work[(r)$val] ]] && echo OK
echo "Array contents are as expected: "
wanted=("$start[@]:0:1" "$start[@]:2")
[[ "$(j.:.)wanted[@]" == "$(j.:.)work[@]" ]] && echo "OK"
echo "-- array contents: start --"
print -l -r -- "-- $#start elements" $(@)start
echo "-- array contents: work --"
print -l -r -- "-- $#work elements" "$work[@]"
Results:
Array size went down by one:
OK
Array item two is now gone:
OK
Array contents are as expected:
OK
-- array contents: start --
-- 5 elements
one
two
three
four 4
five
-- array contents: work --
-- 4 elements
one
three
four 4
five
In ZSH this is dead easy (note this uses more bash compatible syntax than necessary where possible for ease of understanding):
# I always include an edge case to make sure each element
# is not being word split.
start=(one two three 'four 4' five)
work=($(@)start)
idx=2
val=$work[idx]
# How to remove a single element easily.
# Also works for associative arrays (at least in zsh)
work[$idx]=()
echo "Array size went down by one: "
[[ $#work -eq $(($#start - 1)) ]] && echo "OK"
echo "Array item "$val" is now gone: "
[[ -z $work[(r)$val] ]] && echo OK
echo "Array contents are as expected: "
wanted=("$start[@]:0:1" "$start[@]:2")
[[ "$(j.:.)wanted[@]" == "$(j.:.)work[@]" ]] && echo "OK"
echo "-- array contents: start --"
print -l -r -- "-- $#start elements" $(@)start
echo "-- array contents: work --"
print -l -r -- "-- $#work elements" "$work[@]"
Results:
Array size went down by one:
OK
Array item two is now gone:
OK
Array contents are as expected:
OK
-- array contents: start --
-- 5 elements
one
two
three
four 4
five
-- array contents: work --
-- 4 elements
one
three
four 4
five
edited Aug 11 '18 at 8:22
answered Apr 9 '16 at 10:11
trevorjtrevorj
743 bronze badges
743 bronze badges
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
add a comment |
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
Sorry, just tried. It did not work in zsh for an assoziative array
– Falk
Dec 8 '18 at 22:43
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
It works just fine, I just tested it (again). Things not working for you? Please explain what did not work exactly in as much detail as you can. What ZSH version are you using?
– trevorj
Apr 2 at 2:51
add a comment |
There is also this syntax, e.g. if you want to delete the 2nd element :
array=("$array[@]:0:1" "$array[@]:2")
which is in fact the concatenation of 2 tabs. The first from the index 0 to the index 1 (exclusive) and the 2nd from the index 2 to the end.
add a comment |
There is also this syntax, e.g. if you want to delete the 2nd element :
array=("$array[@]:0:1" "$array[@]:2")
which is in fact the concatenation of 2 tabs. The first from the index 0 to the index 1 (exclusive) and the 2nd from the index 2 to the end.
add a comment |
There is also this syntax, e.g. if you want to delete the 2nd element :
array=("$array[@]:0:1" "$array[@]:2")
which is in fact the concatenation of 2 tabs. The first from the index 0 to the index 1 (exclusive) and the 2nd from the index 2 to the end.
There is also this syntax, e.g. if you want to delete the 2nd element :
array=("$array[@]:0:1" "$array[@]:2")
which is in fact the concatenation of 2 tabs. The first from the index 0 to the index 1 (exclusive) and the 2nd from the index 2 to the end.
edited Jan 25 at 17:14
gniourf_gniourf
32.3k5 gold badges69 silver badges84 bronze badges
32.3k5 gold badges69 silver badges84 bronze badges
answered Jan 25 at 17:01
OphyTeOphyTe
338 bronze badges
338 bronze badges
add a comment |
add a comment |
Partial answer only
To delete the first item in the array
unset 'array[0]'
To delete the last item in the array
unset 'array[-1]'
add a comment |
Partial answer only
To delete the first item in the array
unset 'array[0]'
To delete the last item in the array
unset 'array[-1]'
add a comment |
Partial answer only
To delete the first item in the array
unset 'array[0]'
To delete the last item in the array
unset 'array[-1]'
Partial answer only
To delete the first item in the array
unset 'array[0]'
To delete the last item in the array
unset 'array[-1]'
edited Jan 25 at 17:15
gniourf_gniourf
32.3k5 gold badges69 silver badges84 bronze badges
32.3k5 gold badges69 silver badges84 bronze badges
answered Aug 19 '18 at 9:17
consideRatioconsideRatio
7069 silver badges14 bronze badges
7069 silver badges14 bronze badges
add a comment |
add a comment |
To avoid conflicts with array index using unset
- see https://stackoverflow.com/a/49626928/3223785 and https://stackoverflow.com/a/47798640/3223785 for more information - reassign the array to itself: ARRAY_VAR=($ARRAY_VAR[@])
.
#!/bin/bash
ARRAY_VAR=(0 1 2 3 4 5 6 7 8 9)
unset ARRAY_VAR[5]
unset ARRAY_VAR[4]
ARRAY_VAR=($ARRAY_VAR[@])
echo $ARRAY_VAR[@]
A_LENGTH=$#ARRAY_VAR[*]
for (( i=0; i<=$(( $A_LENGTH -1 )); i++ )) ; do
echo ""
echo "INDEX - $i"
echo "VALUE - $ARRAY_VAR[$i]"
done
exit 0
[Ref.: https://tecadmin.net/working-with-array-bash-script/ ]
add a comment |
To avoid conflicts with array index using unset
- see https://stackoverflow.com/a/49626928/3223785 and https://stackoverflow.com/a/47798640/3223785 for more information - reassign the array to itself: ARRAY_VAR=($ARRAY_VAR[@])
.
#!/bin/bash
ARRAY_VAR=(0 1 2 3 4 5 6 7 8 9)
unset ARRAY_VAR[5]
unset ARRAY_VAR[4]
ARRAY_VAR=($ARRAY_VAR[@])
echo $ARRAY_VAR[@]
A_LENGTH=$#ARRAY_VAR[*]
for (( i=0; i<=$(( $A_LENGTH -1 )); i++ )) ; do
echo ""
echo "INDEX - $i"
echo "VALUE - $ARRAY_VAR[$i]"
done
exit 0
[Ref.: https://tecadmin.net/working-with-array-bash-script/ ]
add a comment |
To avoid conflicts with array index using unset
- see https://stackoverflow.com/a/49626928/3223785 and https://stackoverflow.com/a/47798640/3223785 for more information - reassign the array to itself: ARRAY_VAR=($ARRAY_VAR[@])
.
#!/bin/bash
ARRAY_VAR=(0 1 2 3 4 5 6 7 8 9)
unset ARRAY_VAR[5]
unset ARRAY_VAR[4]
ARRAY_VAR=($ARRAY_VAR[@])
echo $ARRAY_VAR[@]
A_LENGTH=$#ARRAY_VAR[*]
for (( i=0; i<=$(( $A_LENGTH -1 )); i++ )) ; do
echo ""
echo "INDEX - $i"
echo "VALUE - $ARRAY_VAR[$i]"
done
exit 0
[Ref.: https://tecadmin.net/working-with-array-bash-script/ ]
To avoid conflicts with array index using unset
- see https://stackoverflow.com/a/49626928/3223785 and https://stackoverflow.com/a/47798640/3223785 for more information - reassign the array to itself: ARRAY_VAR=($ARRAY_VAR[@])
.
#!/bin/bash
ARRAY_VAR=(0 1 2 3 4 5 6 7 8 9)
unset ARRAY_VAR[5]
unset ARRAY_VAR[4]
ARRAY_VAR=($ARRAY_VAR[@])
echo $ARRAY_VAR[@]
A_LENGTH=$#ARRAY_VAR[*]
for (( i=0; i<=$(( $A_LENGTH -1 )); i++ )) ; do
echo ""
echo "INDEX - $i"
echo "VALUE - $ARRAY_VAR[$i]"
done
exit 0
[Ref.: https://tecadmin.net/working-with-array-bash-script/ ]
answered Jun 21 at 15:11
Eduardo LucioEduardo Lucio
4266 silver badges16 bronze badges
4266 silver badges16 bronze badges
add a comment |
add a comment |
What I do is:
array="$(echo $array | tr ' ' 'n' | sed "/itemtodelete/d")"
BAM, that item is removed.
1
This breaks forarray=('first item' 'second item')
.
– Benjamin W.
Jun 14 '16 at 17:17
add a comment |
What I do is:
array="$(echo $array | tr ' ' 'n' | sed "/itemtodelete/d")"
BAM, that item is removed.
1
This breaks forarray=('first item' 'second item')
.
– Benjamin W.
Jun 14 '16 at 17:17
add a comment |
What I do is:
array="$(echo $array | tr ' ' 'n' | sed "/itemtodelete/d")"
BAM, that item is removed.
What I do is:
array="$(echo $array | tr ' ' 'n' | sed "/itemtodelete/d")"
BAM, that item is removed.
edited May 24 '16 at 17:34
zx485
16.8k13 gold badges32 silver badges48 bronze badges
16.8k13 gold badges32 silver badges48 bronze badges
answered May 24 '16 at 17:13
garfieldgarfield
71 bronze badge
71 bronze badge
1
This breaks forarray=('first item' 'second item')
.
– Benjamin W.
Jun 14 '16 at 17:17
add a comment |
1
This breaks forarray=('first item' 'second item')
.
– Benjamin W.
Jun 14 '16 at 17:17
1
1
This breaks for
array=('first item' 'second item')
.– Benjamin W.
Jun 14 '16 at 17:17
This breaks for
array=('first item' 'second item')
.– Benjamin W.
Jun 14 '16 at 17:17
add a comment |
This is a quick-and-dirty solution that will work in simple cases but will break if (a) there are regex special characters in $delete
, or (b) there are any spaces at all in any items. Starting with:
array+=(pluto)
array+=(pippo)
delete=(pluto)
Delete all entries exactly matching $delete
:
array=(`echo $array | fmt -1 | grep -v "^$delete$" | fmt -999999`)
resulting inecho $array
-> pippo, and making sure it's an array:echo $array[1]
-> pippo
fmt
is a little obscure: fmt -1
wraps at the first column (to put each item on its own line. That's where the problem arises with items in spaces.) fmt -999999
unwraps it back to one line, putting back the spaces between items. There are other ways to do that, such as xargs
.
Addendum: If you want to delete just the first match, use sed, as described here:
array=(`echo $array | fmt -1 | sed "0,/^$delete$///d;" | fmt -999999`)
add a comment |
This is a quick-and-dirty solution that will work in simple cases but will break if (a) there are regex special characters in $delete
, or (b) there are any spaces at all in any items. Starting with:
array+=(pluto)
array+=(pippo)
delete=(pluto)
Delete all entries exactly matching $delete
:
array=(`echo $array | fmt -1 | grep -v "^$delete$" | fmt -999999`)
resulting inecho $array
-> pippo, and making sure it's an array:echo $array[1]
-> pippo
fmt
is a little obscure: fmt -1
wraps at the first column (to put each item on its own line. That's where the problem arises with items in spaces.) fmt -999999
unwraps it back to one line, putting back the spaces between items. There are other ways to do that, such as xargs
.
Addendum: If you want to delete just the first match, use sed, as described here:
array=(`echo $array | fmt -1 | sed "0,/^$delete$///d;" | fmt -999999`)
add a comment |
This is a quick-and-dirty solution that will work in simple cases but will break if (a) there are regex special characters in $delete
, or (b) there are any spaces at all in any items. Starting with:
array+=(pluto)
array+=(pippo)
delete=(pluto)
Delete all entries exactly matching $delete
:
array=(`echo $array | fmt -1 | grep -v "^$delete$" | fmt -999999`)
resulting inecho $array
-> pippo, and making sure it's an array:echo $array[1]
-> pippo
fmt
is a little obscure: fmt -1
wraps at the first column (to put each item on its own line. That's where the problem arises with items in spaces.) fmt -999999
unwraps it back to one line, putting back the spaces between items. There are other ways to do that, such as xargs
.
Addendum: If you want to delete just the first match, use sed, as described here:
array=(`echo $array | fmt -1 | sed "0,/^$delete$///d;" | fmt -999999`)
This is a quick-and-dirty solution that will work in simple cases but will break if (a) there are regex special characters in $delete
, or (b) there are any spaces at all in any items. Starting with:
array+=(pluto)
array+=(pippo)
delete=(pluto)
Delete all entries exactly matching $delete
:
array=(`echo $array | fmt -1 | grep -v "^$delete$" | fmt -999999`)
resulting inecho $array
-> pippo, and making sure it's an array:echo $array[1]
-> pippo
fmt
is a little obscure: fmt -1
wraps at the first column (to put each item on its own line. That's where the problem arises with items in spaces.) fmt -999999
unwraps it back to one line, putting back the spaces between items. There are other ways to do that, such as xargs
.
Addendum: If you want to delete just the first match, use sed, as described here:
array=(`echo $array | fmt -1 | sed "0,/^$delete$///d;" | fmt -999999`)
edited Nov 1 '16 at 14:44
answered Nov 1 '16 at 14:16
Joshua GoldbergJoshua Goldberg
2,90919 silver badges35 bronze badges
2,90919 silver badges35 bronze badges
add a comment |
add a comment |
How about something like:
array=(one two three)
array_t=" $array[@] "
delete=one
array=($array_t// $delete / )
unset array_t
add a comment |
How about something like:
array=(one two three)
array_t=" $array[@] "
delete=one
array=($array_t// $delete / )
unset array_t
add a comment |
How about something like:
array=(one two three)
array_t=" $array[@] "
delete=one
array=($array_t// $delete / )
unset array_t
How about something like:
array=(one two three)
array_t=" $array[@] "
delete=one
array=($array_t// $delete / )
unset array_t
answered Jun 28 '17 at 0:11
user8223227user8223227
1
1
add a comment |
add a comment |
#/bin/bash
echo "# define array with six elements"
arr=(zero one two three 'four 4' five)
echo "# unset by index: 0"
unset -v 'arr[0]'
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
arr_delete_by_content() # value to delete
for i in $!arr[*]; do
[ "$arr[$i]" = "$1" ] && unset -v 'arr[$i]'
done
echo "# unset in global variable where value: three"
arr_delete_by_content three
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
echo "# rearrange indices"
arr=( "$arr[@]" )
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_value() sed 's,^[^=]*=,,'
echo "# new array without value: two"
declare -a arr="$(delete_value two "$arr[@]")"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_values() # arraydecl values..., returns array decl. (keeps indices)
declare -a arr="$1"; local i v; shift
for v in "$@"; do
for i in $!arr[*]; do
[ "$v" = "$arr[$i]" ] && unset -v 'arr[$i]'
done
done
declare -p arr
echo "# new array without values: one five (keep indices)"
declare -a arr="$(delete_values "$(declare -p arr|sed 's,^[^=]*=,,')" one five)"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
# new array without multiple values and rearranged indices is left to the reader
1
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
add a comment |
#/bin/bash
echo "# define array with six elements"
arr=(zero one two three 'four 4' five)
echo "# unset by index: 0"
unset -v 'arr[0]'
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
arr_delete_by_content() # value to delete
for i in $!arr[*]; do
[ "$arr[$i]" = "$1" ] && unset -v 'arr[$i]'
done
echo "# unset in global variable where value: three"
arr_delete_by_content three
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
echo "# rearrange indices"
arr=( "$arr[@]" )
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_value() sed 's,^[^=]*=,,'
echo "# new array without value: two"
declare -a arr="$(delete_value two "$arr[@]")"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_values() # arraydecl values..., returns array decl. (keeps indices)
declare -a arr="$1"; local i v; shift
for v in "$@"; do
for i in $!arr[*]; do
[ "$v" = "$arr[$i]" ] && unset -v 'arr[$i]'
done
done
declare -p arr
echo "# new array without values: one five (keep indices)"
declare -a arr="$(delete_values "$(declare -p arr|sed 's,^[^=]*=,,')" one five)"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
# new array without multiple values and rearranged indices is left to the reader
1
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
add a comment |
#/bin/bash
echo "# define array with six elements"
arr=(zero one two three 'four 4' five)
echo "# unset by index: 0"
unset -v 'arr[0]'
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
arr_delete_by_content() # value to delete
for i in $!arr[*]; do
[ "$arr[$i]" = "$1" ] && unset -v 'arr[$i]'
done
echo "# unset in global variable where value: three"
arr_delete_by_content three
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
echo "# rearrange indices"
arr=( "$arr[@]" )
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_value() sed 's,^[^=]*=,,'
echo "# new array without value: two"
declare -a arr="$(delete_value two "$arr[@]")"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_values() # arraydecl values..., returns array decl. (keeps indices)
declare -a arr="$1"; local i v; shift
for v in "$@"; do
for i in $!arr[*]; do
[ "$v" = "$arr[$i]" ] && unset -v 'arr[$i]'
done
done
declare -p arr
echo "# new array without values: one five (keep indices)"
declare -a arr="$(delete_values "$(declare -p arr|sed 's,^[^=]*=,,')" one five)"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
# new array without multiple values and rearranged indices is left to the reader
#/bin/bash
echo "# define array with six elements"
arr=(zero one two three 'four 4' five)
echo "# unset by index: 0"
unset -v 'arr[0]'
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
arr_delete_by_content() # value to delete
for i in $!arr[*]; do
[ "$arr[$i]" = "$1" ] && unset -v 'arr[$i]'
done
echo "# unset in global variable where value: three"
arr_delete_by_content three
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
echo "# rearrange indices"
arr=( "$arr[@]" )
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_value() sed 's,^[^=]*=,,'
echo "# new array without value: two"
declare -a arr="$(delete_value two "$arr[@]")"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
delete_values() # arraydecl values..., returns array decl. (keeps indices)
declare -a arr="$1"; local i v; shift
for v in "$@"; do
for i in $!arr[*]; do
[ "$v" = "$arr[$i]" ] && unset -v 'arr[$i]'
done
done
declare -p arr
echo "# new array without values: one five (keep indices)"
declare -a arr="$(delete_values "$(declare -p arr|sed 's,^[^=]*=,,')" one five)"
for i in $!arr[*]; do echo "arr[$i]=$arr[$i]"; done
# new array without multiple values and rearranged indices is left to the reader
answered Oct 17 '17 at 19:16
Gombok ArthurGombok Arthur
1
1
1
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
add a comment |
1
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
1
1
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
Can you add some comments or a description to tell us about your answer?
– Michael
Oct 17 '17 at 19:26
add a comment |
protected by codeforester Sep 15 '18 at 1:16
Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).
Would you like to answer one of these unanswered questions instead?
Which shell? Your example looks like
zsh
.– chepner
May 31 '13 at 16:30
array=( $array[@]/$delete )
works as expected in Bash. Have you simply missed the=
?– Ken Sharp
Jan 17 '18 at 19:56
@Ken, that's not quite what's wanted - it will remove any matches from each string, and leave empty strings in the array where it matches the whole string.
– Toby Speight
Feb 27 at 15:05