Странное поведение при вычитании 2-х строковых массивов - PullRequest
1 голос
/ 01 октября 2019

Я вычитаю array1 из array2 Мои 2 массива

array1=(apps argocd cache core dev-monitoring-busk test-ci-cd)
array2=(apps argocd cache core default kube-system kube-public kube-node-lease monitoring)

И то, как я их вычитаю,

for i in "${array2[@]}"; do
         array1=(${array1[@]//$i})
done

echo ${array1[@]}

Теперь мой ожидаемый результат должен быть

dev-monitoring-busk test-ci-cd

Но мой ожидаемый результат -

dev--busk test-ci-cd

Хотя вычитание выглядит хорошо, но оно также удаляет строку monitoring из dev-monitoring-busk. Я не понимаю почему. Кто-нибудь может указать, что здесь не так?

Я знаю, что существуют другие решения для различий между двумя массивами, такие как

echo ${Array1[@]} ${Array2[@]} | tr ' ' '\n' | sort | uniq -u

Но это больше разница, а не вычитание,Так что это не работает для меня.

Ответы [ 2 ]

0 голосов
/ 01 октября 2019

Если я правильно понимаю, вам нужно не вычесть array1 из array2, а вычесть array2 из array1. Как указывают другие, замена bash не работает с массивами. Вместо этого вы можете использовать associative array, если ваша версия bash> = 4.2.

Пожалуйста, попробуйте следующее:

declare -a array1=(apps argocd cache core dev-monitoring-busk test-ci-cd)
declare -a array2=(apps argocd cache core default kube-system kube-public kube-node-lease monitoring)

declare -A mark
declare -a ans

for e in "${array2[@]}"; do
    mark[$e]=1
done

for e in "${array1[@]}"; do
    [[ ${mark[$e]} ]] || ans+=( "$e" )
done

echo "${ans[@]}"
  • Сначала она перебирает array2 и отмечаетего элементы с использованием ассоциативного массива mark.
  • Затем он перебирает array1 и добавляет элемент в answer, если его нет в mark.
0 голосов
/ 01 октября 2019

Бит клуджа, но он работает ...

  • используйте comm, чтобы найти элементы, уникальные для (отсортированного) набора данных
  • используйте tr для преобразованиямежду пробелами ('' == разделитель элементов массива) и возвратом каретки ('\ n'; comm работает с отдельными строками)
  • echo "${array1[@]}" | tr ' ' '\n' | sort: преобразовать элементы массива в отдельные строки и отсортировать
  • comm -23 (sorted data set #1) (sorted data set #2): сравнить отсортированные наборы данных и вернуть строки, которые существуют только в наборе данных # 1

Объединение всего этого вместе дает нам:

$ array1=(apps argocd cache core dev-monitoring-busk test-ci-cd)
$ array2=(apps argocd cache core default kube-system kube-public kube-node-lease monitoring)

# find rows that only exist in array1

$ comm -23 <(echo "${array1[@]}" | tr ' ' '\n' | sort) <(echo "${array2[@]}" | tr ' ' '\n' | sort)
dev-monitoring-busk
test-ci-cd

# same thing but this time replace carriage returns with spaces (ie, pull all items onto a single line of output):

$ comm -23 <(echo "${array1[@]}" | tr ' ' '\n' | sort) <(echo "${array2[@]}" | tr ' ' '\n' | sort) | tr '\n' ' '
dev-monitoring-busk test-ci-cd

ПРИМЕЧАНИЕ оcomm:

- takes 2 sorted data sets as input
- generates 3 columns of output:
    - (output column #1) rows only in data set #1
    - (output column #2) rows only in data set #2
    - (output column #3) rows in both data sets #1 and #2
- `comm -xy` ==> discard ouput columns 'x' and 'y'
    - `comm -12` => discard output columns #1 and #2 => only show lines common to both data sets (output column #3)
    - `comm -23' => discard output columns #2 and #3 => only show lines that exist in data set #1 (output column #1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...