niglesias
niglesias

Reputation: 447

Bash: How to select elements in array

I have an array with subdirs and files:

~$ array=(elem1/a elem1/b elem2/a elem2/b)

I need to select all files (with its subdir) inside subdir elem1.

I've tried with a for loop and case:

for element in "${array[@]}"; do
  case $element in
    elem1*)
    # action I need to perform on this element
      echo "This is $element"
    ;;
  esac
done

I'd like to get the list of elements I need using some glob, in a similar way as this (which substracts substrings from array elements):

~$ echo ${array[@]%/a}
elem1 elem1/b elem2 elem2/b

My main concern is that I shoudn't hardcode what strings I'm searching for, as I don't know its contents - in my final version of this script I'm getting them from another array.

Upvotes: 1

Views: 2415

Answers (3)

Jdamian
Jdamian

Reputation: 3125

My answer prints every element of the array in a different line, then filters the ones you are interested (grep) and put them into a new array

newarray=( $(printf "%s\n" "${array[@]}" | grep ^elem/) )

The only problem would be if the elements of your array (subdirs and file namews) might contain EOL or blank chars.

Bonus

If your elements contain EOL or blank chars, you should use the NUL (\000) char and grep -zZ to handle it; but then you need more code to turn out those NUL-char strings into something which the bash can work with -- the bash stops reading when it finds a NUL char.

In this example I use awk, which has no problem to handle NUL chars, and makes unnecessary the use of grep:

 eval newarray=( $(printf "%s\000" "${A[@]}" |
                   awk 'BEGIN { FS="\000" }

                        /^elem\// {
                                    gsub("\042","\\\042")
                                    printf("[" NR-1 "]=\042%s\042 ",$0)
                                  }'
                   )
                )

Upvotes: 2

randomir
randomir

Reputation: 18697

You can filter your array with a variable query (prefix below) and store the results in a new array (result):

#!/bin/bash
array=(elem1/a elem1/b elem2/a elem2/b)
prefix=elem1
result=()
for element in "${array[@]}"; do
    [[ $element == $prefix/* ]] && result+=("$element")
done

The result is:

$ declare -p result
declare -a result='([0]="elem1/a" [1]="elem1/b")'

Upvotes: 2

karakfa
karakfa

Reputation: 67507

here is one alternative

$ for e in "${array[@]}"; 
  do case "${e%%/*}" in
       elem1) echo "$e is in elem1" ;;
     esac
  done

elem1/a is in elem1
elem1/b is in elem1

Upvotes: 1

Related Questions