6

我遇到了这个很酷的 Bash 函数来检查一个数组是否包含一个元素:

CONTAINS_ELEMENT(){
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

这是它的用法示例:

if CONTAINS_ELEMENT $element "${array[@]}"; then
... 
fi

我的问题是:有没有办法重写这个函数,以便它可以检查一个数组中的任何值是否等于另一个数组中的任何值,而不是像现在那样只检查一个值?

4

4 回答 4

3

更正#3

试试下面的代码。ArrContains取两个参数,两个数组的名称。它创建一个临时散列lArr1,然后检查散列中是否有任何元素lArr2。这样for可以避免嵌入的循环。

#!/usr/bin/bash

ArrContains(){
  local lArr1 lArr2
  declare -A tmp
  eval lArr1=("\"\${$1[@]}\"")
  eval lArr2=("\"\${$2[@]}\"")
  for i in "${lArr1[@]}";{ ((++tmp['$i']));}
  for i in "${lArr2[@]}";{ [ -n "${tmp[$i]}" ] && return 0;}
  return 1
}

arr1=("a b" b c)
arr2=(x 'b c' e)
arr3=(q a\ b y)
ArrContains arr1 arr2 && echo Contains arr1 arr2
ArrContains arr1 arr3 && echo Contains arr1 arr3

输出:

Contains arr1 arr3

其他方法可能是定义一些分隔字符并连接第一个哈希。然后搜索匹配的SEPitemSEP字符串。

ArrContainsRe(){
  local lArr1 lArr2 tmp
  eval lArr1=("\"\${$1[@]}\"")
  printf -v tmp ",%s" "${lArr1[@]}";
  tmp="$tmp,"
  eval lArr2=("\"\${$2[@]}\"")
  for i in "${lArr2[@]}";{ [[ $tmp =~ ,$i, ]] && return 0;}
  return 1
}
...
ArrContainsRe arr1 arr2 && echo ContainsRe arr1 arr2
ArrContainsRe arr1 arr3 && echo ContainsRe arr1 arr3

输出:

ContainsRe arr1 arr3
于 2013-06-11T11:09:46.687 回答
1

循环内循环:

#!/bin/bash
clear

arrA=("a" "b" "c" "d" "e" "f")
arrZERO=("c" "e") # must be turned to "0"

echo "arrA:"
echo ${arrA[@]}
echo ""
echo "arrZERO:"
echo ${arrZERO[@]}

for (( i=0; i < ${#arrA[@]}; i++ ))
do
    for (( j=0; j < ${#arrZERO[@]}; j++ ))
    do
        if [[ ${arrA[$i]} = ${arrZERO[$j]} ]]; then
            arrA[$i]="0"
        fi
    done
done

echo ""
echo "FINAL"
echo ${arrA[@]}

终端将显示:

arrA:
a b c d e f

arrZERO:
c e

FINAL
a b 0 d 0 f
于 2020-05-31T17:16:20.630 回答
0

查看上面的链接,我找到了一个几乎可以完成我需要它做的事情的解决方案,但不完全是:

parameters=($1 $2 $3 $4)
arg1=(h help -h --help)

PARAMETERS(){
pr1=" $parameters[@]} "
for item in ${@:1}; do
  if [[ $pr1 =~ " $item " ]]; then
    return 0
  else
    return 1
  fi
done
}

if PARAMETERS "${arg1[@]}"; then
  echo "It works!"
else
  echo "Nope, still not working..."
fi

现在,此代码在传递参数“h”时有效,但在传递数组中的其他参数时无效(-h --help 帮助)。抱歉,如果我在这里犯了一些愚蠢的错误,那么当谈到 bash 脚本时,我有点讨厌 :)

于 2013-06-11T12:38:31.997 回答
-1

这应该这样做:

any_overlap() {
    for e1 in "${array1[@]}"
    do
        for e2 in "${array2[@]}"
        do
            if [[ "$e1" = "$e2" ]]
            then
                return 0
            fi
        done
    done
    return 1
}

测试环节:

$ array1=(foo bar baz) array2=(ban bat bar) && any_overlap; echo $?
0
$ array1=(foo bar baz) array2=(ban bat) && any_overlap; echo $?
1
$ array1=() array2=() && any_overlap; echo $?
1

当然,如果数组已排序或数组元素都不包含空格,则有更快的方法来执行此操作。

于 2013-06-11T10:53:59.530 回答