-2

I have two lists.

I have to check if there is a tar.gz which name contains a substring like aa or ab and so on. I'm using this little function: How do you tell if a string contains another string in POSIX sh?

local=(aa ab ac ad ae)
remote=(ab.tar.gz ac.tar.gz ad.tar.gz ae.tar.gz af.tar.gz)

contains() { test -n "$1" || test -z "$2" && test -z "${1##*"$2"*}"; }
for le in "${local[@]}"; do
    for re in "${remote[@]}"; do
        contains "$re" "$le" && to_dl+=("$re")
    done
done

This works well for me, but I need a second list, which contains the elements of the local list, that don't have a match in the remote list.

michel
  • 11
  • 1
  • 4

2 Answers2

0

Consider just grep -f.

$ tmp=$(printf "%s\n" "${remote[@]}" | grep -Ff <(printf "%s\n" "${local[@]}"))
$ readarray -t to_dl <<<"$tmp"
$ declare -p to_dl
declare -a to_dl=([0]="ab.tar.gz" [1]="ac.tar.gz" [2]="ad.tar.gz" [3]="ae.tar.gz")

I need a second list, which contains the elements of the local list, that don't have a match in the remote list.

Use grep -v.

In your code, just use if. Overall, prefer if over any &&.

if contains "$re" "$le"; then
    to_dl+=("$re")
else
    secondlist+=("$re")
fi
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Thank you, @KamilCuk. Maybe my example or explanation is bad. `local=(aa ab ac ad ae ag) remote=(ab.tar.gz ac.tar.gz ad.tar.gz ae.tar.gz af.tar.gz)` Result should be: `to_dl=(ab.tar.gz ac.tar.gz ad.tar.gz ae.tar.gz) not_there=(aa ag)` – michel Jun 12 '23 at 10:14
0

Small modification to OP's current code:

local=(aa ab ac ad ae)
remote=(ab.tar.gz ac.tar.gz ad.tar.gz ae.tar.gz af.tar.gz)

unset to_dl not_there           # or: to_dl=() not_there=()

contains() { test -n "$1" || test -z "$2" && test -z "${1##*"$2"*}"; }

for le in "${local[@]}"
do
    for re in "${remote[@]}"
    do
        contains "$re" "$le" && { to_dl+=("$re"); continue 2; }
    done
    not_there+=("$le")
done

Where:

  • continue 2 - if we find a match then skip to the next substring (le) in the list
  • not_there+=("$le") - if inner loop finds no matches then save the substring in a different array

Results:

$ typeset -p to_dl not_there
declare -a to_dl=([0]="ab.tar.gz" [1]="ac.tar.gz" [2]="ad.tar.gz" [3]="ae.tar.gz")
declare -a not_there=([0]="aa")
markp-fuso
  • 28,790
  • 4
  • 16
  • 36