Bash:从另一个数组中删除一个数组中存在的项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10020148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:57:07  来源:igfitidea点击:

Bash: Delete items present in one array from another

arraysbashfor-loop

提问by user708516

This entry appears to be about 80% of what I want to do but nothing I've come up with is working: bash: how to delete elements from an array based on a pattern

这个条目似乎是我想做的事情的 80% 左右,但我想出的一切都不起作用: bash:如何根据模式从数组中删除元素

I have two arrays:

我有两个数组:

@tapes_in_drives=(SP1026,SP0995,SP0434)

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

I need a bash solution that can delete all entries present in @tapes_in_drives from @tapes.

我需要一个 bash 解决方案,它可以从@tapes 中删除@tapes_in_drives 中存在的所有条目。

I am building a script to automate the ejection of tapes from a tape library based on expiration date, etc.

我正在构建一个脚本来根据到期日期等自动从磁带库中弹出磁带。

I tried this:

我试过这个:

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

but it doesn't work, nothing is removed.

但它不起作用,没有任何东西被删除。

Thanks for any help you can provide.

感谢您的任何帮助,您可以提供。

EDIT:

编辑:

Here is the code I'm using, I wrote this in Perl originally, hence the @variable definitions and I was super tired when I wrote this question.

这是我正在使用的代码,我最初是用 Perl 编写的,因此是 @variable 定义,当我写这个问题时我非常累。

CODE:

代码:

#!/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[@]}

Results:

结果:

Getting tape list

获取磁带列表

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 SP0983 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

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 SP0983 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 SP1027 SP132

Tapes in Drives:

驱动器中的磁带:

SP1001 SP1038 SP0923 SP0926 SP0925

SP1001 SP1038 SP0923 SP0926 SP0925

Tape List 2

磁带列表 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 SP0983 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

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 SP0983 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 SP1027 SP132

As you can see, the tape names from tapes_in_drives are not being removed from the tapes array.

如您所见,tapes_in_drives 中的磁带名称并未从磁带阵列中删除。

回答by je4d

As a comment said, it's just syntax errors.

正如评论所说,这只是语法错误。

Space-delimit the array entries, don't use the @, and the function is fine for your example data. Note that it removes any entry containing an entry in tapes_in_drives, not just those that match an entry it exactly.

用空格分隔数组条目,不要使用@,该函数适用于您的示例数据。请注意,它会删除包含 中条目的任何条目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

Results:

结果:

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

$

EDITto respond to the edit in the question

编辑以回应问题中的编辑

This line:

这一行:

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

And this line:

而这一行:

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 }'`

initialise tapesand tapes)in_drivesas strings, not arrays. You need to add parentheses around the value being assigned to make them into arrays, or the loop won't work. You can also drop the export, it isn't necessary unless you want processes spawned by the script to inherit those shell variables as environment variables.

初始化tapestapes)in_drives作为字符串,而不是数组。您需要在被分配的值周围添加括号以使其成为数组,否则循环将不起作用。您也可以删除export,除非您希望脚本生成的进程将这些 shell 变量作为环境变量继承,否则没有必要。

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 }'`)

回答by Fritz G. Mehner

Another solution:

另一种解决方案:

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

回答by mivk

Stolen from this answerand adapted to your variables:

这个答案中窃取并适应您的变量:

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

free_tapes=( $(printf "%s\n" "${tapes[@]}" "${tapes_in_drives[@]}" | sort | uniq -u) )

echo "${free_tapes[@]}"

Output:

输出:

SP0001 SP0002 SP2000 SP3000

The -uswitch to uniqmakes it "only print unique lines", so it excludes the tapes which are in both arrays.

-u开关以uniq使得它“只打印独特线”,因此它不包括这是在两个阵列的磁带。