-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.

2
  • What do you want to achieve with the list? where is the second list? Commented Jun 12, 2023 at 8:26
  • please update the question with the current output and the desired output Commented Jun 12, 2023 at 11:39

2 Answers 2

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")
Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.