linux - Remove (not just unset) multiple strings from an array without knowing their positions -


say have arrays

a1=(cats,cats.in,catses,dogs,dogs.in,dogses) a2=(cats.in,dogs.in) 

i want remove a1 matches strings in a2 after removing ".in" , in addition ones match completely(including ".in").

so a1, want remove cats, cats.in, dogs, dogs.in, not catses or dogses.

i think i'll have in 2 steps. found how cut ".in" away:

for elem in "${a2[@]}" ;      var="${elem}"     len="${#var}"     pref=${var:0:len-3} done 

^ gives me "cats" , "dogs"

what command need add loop remove each elem a1?

seems me easiest way solve nested for loops:

#!/usr/bin/env bash  a1=(cats cats.in catses dogs dogs.in dogses) a2=(cats.in dogs.in)  x in "${!a1[@]}";                # step through a1 index   y in "${a2[@]}";               # step through a2 content     if [[ "${a1[x]}" = "$y" || "${a1[x]}" = "${y%.in}" ]];       unset a1[x]     fi   done done  declare -p a1 

but depending on actual data, following might better, using 2 separate loops instead of nesting.

#!/usr/bin/env bash  a1=(cats cats.in catses dogs dogs.in dogses) a2=(cats.in dogs.in)  # flip "a2" array "b", stripping ".in" go... declare -a b=() x in "${!a2[@]}";   b[${a2[x]%.in}]="$x" done  # check existence of stripped version of array content # index of associative array created above. x in "${!a1[@]}";   [[ -n "${b[${a1[x]%.in}]}" ]] && unset a1[$x] a1[${x%.in}] done  declare -p a1 

the advantage here instead of looping through of a2 each item in a1, loop once on each array. down sides might depend on data. example, if contents of a2 large, might hit memory limits. of course, can't know included in question; solution works data provided.

note: solution depends on associative array, feature introduced bash in version 4. if you're running old version of bash, might time upgrade. :)


Comments