How to unset range of array in Bash
Solution 1
One thing to bear in mind is that bash
implemented arrays like ksh
, that is as associative arrays where keys are limited to positive integers (contrary to other languages like perl
or zsh
for instance).
In:
a[123]=foo a[456]=bar a[789]=baz
In bash, you've got an associative array with 3 elements, while in perl
, you'd have an array with 790 elements (789 with zsh).
In ksh
or bash
, ${a[@]:0:1}
returns the first element of the array in the list of elements sorted numerically by key where the key is greater or equal to 0. So in that case, it returns ${a[123]}
, not ${a[0]}
.
unset 'a[123]'
(remember to quote it, otherwise it would fail if there was a file called a1 or a2 or a3 in the current directory) makes sense, as it removes a particular key in the array.
unset 'a[@]::2'
makes less sense though. bash
only understands unset a
, unset 'a[123]'
or unset 'a[*/@]'
, anything after is ignored, so unset 'a[@]::2'
and unset 'a[@]please'
do the same: unset the whole array.
If you want to unset a range of keys, you'd need to loop through the keys:
To get the list of keys of the array, the syntax is "${!a[@]}"
. Unfortunately, applying a range to that doesn't work with bash
nor ksh
, so you'd need a temporary array:
keys=("${!a[@]}")
for i in "${keys[@]::2}"; do unset "a[$i]"; done
Now if you want to consider those arrays like in other languages, you don't want to use unset
. Like, if the array is not sparse in the first place and you want to keep it so (that is shift all the elements by 2 instead of unsetting the first two), you can do things like:
a=("${a[@]:2}")
That is reassign the array with the list of elements you want to keep.
For comparison, with zsh
.
a=({1..20})
unset 'a[12,16]'
would set an empty value to elements 12 to 16. while unset 'a[16,20]'
would shrink the array to 15 elements.
a=({1..20})
a[12,16]=()
(still with zsh
) would shift elements 17 to 20 by 5 positions so a[12]
would contain 17
.
Solution 2
If your array is continuous/not sparse (all elements from 0..N-1 set)
You can remove the 2nd element of the array with
unset 'a[1]'
To remove the 2nd, 3rd and 4th element, you can use e.g.
for ((i=1; i<=3; i++)); do unset "a[$i]"; done
To delete all but the 1st and 2nd element, you can use e.g.
for ((i=2; i<${#a[@]}; i++)); do unset "a[$i]"; done
General solution (works also for sparse arrays): You can remove the 2nd element of the array with
unset "a[$(echo ${!a[@]} | cut -d" " -f 2)]"
To remove the 2nd, 3rd and 4th element, you can use e.g.
for $(echo ${!a[@]} | cut -d" " -f 2-4) ; do unset "a[$i]"; done
To delete all but the 1st and 2nd element, you can use e.g.
for $(echo ${!a[@]} | cut -d" " -f 2-) ; do unset "a[$i]"; done
Related videos on Youtube
cableload
Updated on September 18, 2022Comments
-
cableload over 1 year
I want to create a word document with many bookmarks. The bookmarks contains some price information that needs to be updated every year. I need to update them based on value from a database in a certain order. How do i create a bookmark with a bookmark ID or in a particular order for word?? Whats the guarantee that when i read bookmarks from c# using word object model, it will be retrieved in the same order in which it was created?
Edited: The contents of the word document is broken down by columns and each column has many bookmarks to it. I can name bookmarks by bm1c1,bm2c1.., bm1c2,bm2c2 etc...but when bookmarks are read from C#, its reading from bm1c1,bm1c2..etc.....where c1 and c2 represent column info...I want to read bookmarks in the order for a particular column, because the data i am going to replace is coming from a query that has a specific order..So if i can associate a bookmark with a specific id, then i thought it might help...I cant find a way to add a bookmark with specific id...
On further thoughts..i think i could do something like this..locate the relevant bookmark and update it..
Object name = bmrk.Name; //this could be bm1c1 or whatever appropriate Microsoft.Office.Interop.Word.Range rng = doc.Bookmarks.get_Item(ref name).Range; rng.Text = "197.00"; Object range = rng; doc.Bookmarks.Add(bmrk.Name, ref range);
but the problem with this is, if tomorrow i need to add a new bookmark in between two other existing bookmarks, it messes up the order..so if i can specify an id then i maybe able to use that to maintain the order
Thanks
-
Sandeep G B over 12 yearsothers will be able to help you if you can share your findings and any code that you have written.
-
-
Rahul Patil about 11 yearsI already did this n had updated in question.. but question remain about
unset a[@]::2
-
Stéphane Chazelas about 11 yearsThat's wrong in the general case because
${#a[@]}
is the number of elements in the array, not the greatest indice in the array (bash
arrays, likeksh
arrays are sparse, contrary to zsh ones). -
Rahul Patil about 11 years@StephaneChazelas after deleting element why not reset index ?
-
Rahul Patil about 11 years@StephaneChazelas after doing some RnD I Found this way to reset array
a=( $(echo ${a[@]}) )
is this fine ? -
YoloTats.com about 11 years@StephaneChazelas I fixed my answer for sparse arrays, but your answer is more clean.
-
Stéphane Chazelas about 11 years@RahulPatil, if you want to unsparse the array, just write it:
a=("${a[@]}")
, usingecho
and command substitution would only work in limited corner cases (like when none of the elements are empty or contain spc, tab, NL, backslash, *, ?, [ or start with -). -
Rahul Patil about 11 yearsThanks.. you are my master... with help of this , I have solve one problem.. so please have look at this and let me if any improvement in that Bash Code .. unix.stackexchange.com/questions/74001/…