英文:
Check an array of strings against another array - Bash
问题
我有两个列表。
我需要检查是否存在一个包含类似于aa或ab等子字符串的tar.gz文件。
我正在使用这个小函数:
https://stackoverflow.com/questions/2829613/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
这对我来说运行良好,但我需要一个第二个列表,其中包含本地列表中没有在远程列表中找到匹配项的元素。
英文:
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:
https://stackoverflow.com/questions/2829613/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.
答案1
得分: 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
英文:
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
答案2
得分: 0
Sure, here is the translated code:
小修改 OP 当前的代码:
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 # 或者: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
其中:
- `continue 2` - 如果找到匹配项,则跳到列表中的下一个子字符串 (`le`)。
- `not_there+=("$le")` - 如果内部循环未找到匹配项,则将子字符串保存在不同的数组中。
结果:
$ typeset -p to_dl not_there
declare -a to_dl=("ab.tar.gz" "ac.tar.gz" "ad.tar.gz" "ae.tar.gz")
declare -a not_there=("aa")
英文:
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 listnot_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")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论