2013-06-11 2 views
5

я пришел через этот прохладный функции Bash для проверки, если массив содержит элемент:Bash проверка элемент в массиве для элементов другого массива

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

Вот пример его использования:

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

Мой вопрос таков: Есть ли способ переписать эту функцию, чтобы она могла проверить, равно ли какое-либо значение в массиве любому значению с другим массивом, а не просто проверять одно значение , поскольку оно в корне делает эс?

+0

Неправильно! Попробуйте '' $ {@: 2} "'. – TrueY

+0

Очень похоже на вопросы о пересечении массива [1] (http://stackoverflow.com/questions/2696055/intersection-of-two-lists-in-bash) и [2] (http://stackoverflow.com/questions/ 7870230/массив пересечений-в-Баш). – l0b0

+2

Чтобы показать вопрос был решен, отметьте один из ответов как «принятый». – fedorqui

ответ

2

ИСПРАВЛЕНО # 3

Try код ниже. ArrContains возьмите два аргумента, имя двух массивов. Он создает временный хеш от lArr1, а затем проверяет, находятся ли какие-либо элементы lArr2 в хэше. Таким образом можно избежать встроенных for -loops.

#!/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 
+0

@ l0b0: Вы правы! Первая функция плохо справлялась с этим. Я исправил. Благодаря! – TrueY

+0

@ l0b0: Я просто хотел поддержать ваш последний комментарий, но он был удален ...;) В любом случае спасибо за них! – TrueY

+0

Это не удается, когда я пытаюсь. Он ничего не возвращает, несмотря ни на что. –

-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 

Конечно, существуют более быстрые способы сделать это, если массивы сортируются или ни один из элементов массива не содержат пробелов.

+0

Как бы вы взяли два массива в качестве параметров? Это невозможно. – l0b0

+0

Вы можете взять размер первого массива в качестве первого параметра :-) – choroba

+0

«Также, если первые два элемента в соответствующих массивах отличаются друг от друга, он возвращает 0.» Что вы имеете в виду? Я просто протестировал его, и он отлично работает. – l0b0

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 help). Извините, если я делаю какую-то глупую ошибку здесь, я немного нууб, когда дело доходит до сценариев bash :)

+0

Одна проблема синтаксиса: 'pr1 =" $ parameters [@]} "' может быть 'pr1 =" $ {parameters [@]} "'. Но я могу предложить использовать 'local pr1 = ...'. И проблема семантики: 'if' вернется в первом цикле в' PARAMETERS'. Я предполагаю, что часть 'else' не нужна. – TrueY

+0

Хорошо, ваше собственное решение оказалось лучшим способом решения моей проблемы. В очередной раз благодарим за помощь! –

Смежные вопросы