Bash: удаление элементов, присутствующих в одном массиве из другого

эта запись, похоже, составляет около 80% того, что я хочу сделать, но ничего, что я придумал, не работает: bash: как удалить элементы из массива на основе шаблона

у меня есть два массива:

@tapes_in_drives=(SP1026,SP0995,SP0434)

@tapes=(SP0001,SP0002,SP0434,SP0995,SP1026,SP2000,SP3000)

мне нужно решение bash, которое может удалить все записи, присутствующие в @tapes_in_drives из @tapes.

Я создаю сценарий для автоматизации извлечения лент из ленточной библиотеки на основе даты истечения срока действия и т. д.

Я попытался это:

for i in "${tapes_in_drives[@]}"; do
        tapes=(${tapes[@]//*$i*})
done

но это не работает, ничего не удаляется.

Спасибо за любую помощь вы можете предоставить.

EDIT:

вот код, который я использую, я написал это в Perl первоначально, следовательно, определения @ variable, и я был очень устал, когда я написал этот вопрос.

код:

#!/usr/bin/bash

# If media expires less than this many days, keep it
export days_expired="30"

# Set to 1 to get debug output to console
export debug="1"

# Get list of SPxxxxx tapes that are physically in the library
if [ $debug -eq 1 ]; then echo "Getting tape list"; fi
export tapes=`vmquery -rn 1 -b | tail +4 | awk '{print $1}' && vmquery -rn 4 -b | tail +4 | awk '{print $1}'`

if [ $debug -eq 1 ]; then echo ${tapes[@]}; fi

# Query tape drives for tapes
export tapes_in_drives=`ssh srv-reg-nbms-01 "echo 's d q'|/usr/openv/volmgr/bin/tldtest -r /dev/smc0|grep 'Barcode'" | awk '{print }' && ssh srv-reg-nbms-02 "echo 's d q'|/usr/openv/volmgr/bin/tldtest -r /dev/smc0|grep 'Barcode'" | awk '{print }'`

if [ $debug -eq 1 ]; then
    echo ""
    echo "Tapes in Drives:"
    echo ${tapes_in_drives[@]}
    echo "";
fi


# Remove tapes in drives from list of tapes
for i in "${tapes_in_drives[@]}"; do
    tapes=(${tapes[@]//*$i*})
done

echo "Tape List 2"
echo ${tapes[@]}

результаты:

получение списка ленты

SP0011 SP0039 SP0402 SP0434 SP0464 SP0516 SP0551 SP0600 SP0604 SP0726 SP0731 SP0765 SP0767 SP07779 SP0781 SP0787 SP0793 SP0794 SP0805 SP0828 SP0830 SP0832 SP0927 SP0928 SP0936 SP0983 SP0995 SP1001 SP1004 SP1008 SP1015 SP1017 SP1026 SP1033 SP1036 SP1038 SP0042 SP0049 SP0462 SP0473 SP0517 SP0557 SP0560 SP0642 SP0659 SP0697 SP0712 SP0723 SP0766 SP0777 SP0786 SP0788 SP0792 SP0907 SP0910 SP0923 SP0925 SP0926 SP0940 SP0963 SP0981 SP0986 SP0994 SP0994 SP1007 SP1020 SP1021 SP1027 SP1039

ленты в приводах:

SP1001 SP1038 SP0923 SP0926 SP0925

Список Ленты 2

SP0011 SP0039 SP0402 SP0434 SP0464 SP0516 SP0551 SP0600 SP0604 SP0726 SP0731 SP0765 SP0767 SP0779 SP0781 SP0787 SP0793 SP0794 SP0805 SP0828 SP0830 SP0832 SP0927 SP0928 SP0936 SP0995 SP1001 SP1004 SP1008 SP1015 SP1017 SP1026 SP1033 SP1036 SP1038 SP0042 SP0049 SP0150 SP0462 SP0473 SP0517 SP0557 SP0560 SP0642 SP0659 SP0697 SP0712 SP0723 SP0766 SP0777 SP0786 SP0788 SP0792 SP0907 SP0910 SP0923 SP0925 SP0926 SP0940 SP0963 SP0981 SP0986 SP0989 SP0994 SP0999 SP1007 SP1020 SP1021 SP1027 SP1039

как вы можете видеть, имена лент из tapes_in_drives не удаляются из массива лент.

2 ответов


как сказано в комментарии, это просто синтаксические ошибки.

пробел-разделите записи массива, не используйте @, и функция отлично подходит для ваших данных примера. Обратите внимание, что он удаляет любую запись, содержащую запись в tapes_in_drives, а не только те, которые точно соответствуют записи.

tapes=(SP0001 SP0002 SP0434 SP0995 SP1026 SP2000 SP3000)
tapes_in_drives=(SP1026 SP0995 SP0434)
for i in "${tapes_in_drives[@]}"; do
         tapes=(${tapes[@]//*$i*})
done

результаты:

$ echo ${tapes[0]}
SP0001
$ echo ${tapes[1]}
SP0002
$ echo ${tapes[2]}
SP2000
$ echo ${tapes[3]}
SP3000
$ echo ${tapes[4]}

$

редактировать ответить на редактирование в вопросе

эта строка:

export tapes=`vmquery -rn 1 -b | tail +4 | awk '{print $1}' && vmquery -rn 4 -b | tail +4 | awk '{print $1}'`

и этого строка:

export tapes_in_drives=`ssh srv-reg-nbms-01 "echo 's d q'|/usr/openv/volmgr/bin/tldtest -r /dev/smc0|grep 'Barcode'" | awk '{print }' && ssh srv-reg-nbms-02 "echo 's d q'|/usr/openv/volmgr/bin/tldtest -r /dev/smc0|grep 'Barcode'" | awk '{print }'`

инициализации tapes и tapes)in_drives как строки, а не массивы. Вам нужно добавить круглые скобки вокруг назначаемого значения, чтобы сделать их массивами, или цикл не будет работать. Вы также можете отбросить export, это не обязательно, если вы не хотите, чтобы процессы, порожденные скриптом, наследовали эти переменные оболочки как переменные среды.

tapes=(`vmquery -rn 1 -b | tail +4 | awk '{print $1}' && vmquery -rn 4 -b | tail +4 | awk '{print $1}'`)

tapes_in_drives=(`ssh srv-reg-nbms-01 "echo 's d q'|/usr/openv/volmgr/bin/tldtest -r /dev/smc0|grep 'Barcode'" | awk '{print }' && ssh srv-reg-nbms-02 "echo 's d q'|/usr/openv/volmgr/bin/tldtest -r /dev/smc0|grep 'Barcode'" | awk '{print }'`)

другое решение:

tapes_in_drives=( SP1026 SP0995 SP0434 )
tapes=(SP0001 SP0002 SP0434 SP0995 SP1026 SP2000 SP3000)

tps=" ${tapes[*]} "                     # stringify the array

for item in ${tapes_in_drives[@]}; do
  tps=${tps/ ${item} / }                # replace item
done
tapes=( $tps )                          # replace the array