在bash中从一个列表中删除另一个列表中的项

在bash中从一个列表中删除另一个列表中的项,bash,shell,unix,Bash,Shell,Unix,我在下面试着 processed_files_list='file2 file6' input_files='file1 file2 file3 file4 file5 file6 file7' for i in `echo $processed_files_list` do echo "removing '$i'" input_files_new=${input_files//$i/} done echo $input_files_new 输出: removing 'file

我在下面试着

processed_files_list='file2 file6'
input_files='file1 file2 file3 file4 file5 file6 file7'
for i in `echo $processed_files_list`
do
    echo "removing '$i'"
    input_files_new=${input_files//$i/}
done
echo $input_files_new
输出:

removing 'file2'
removing 'file6'
[user@desk ~]$ echo $input_files_new
file1 file2 file3 file4 file5 file7

但是上面并没有删除第一部分,在这种情况下,它是文件2…为什么会发生这种情况?

以下是问题的简单版本:

files="foo"
files_new="$files bar"
files_new="$files baz"
echo "$files_new"
这个输出

foo baz
那么
条发生了什么事

这些更改被覆盖,因为您复制并修改了原始列表而不是工作列表。因此,您只能看到最新的更改,而不能看到累积的更改

您可以通过首先设置

input_files_new="$input_files"
然后每次更新该列表:

input_files_new=${input_files_new//$i/}

<>但是,您应该考虑使用适当的数组,因为在字符串中替换<代码>文件1>代码>也会影响<代码>文件10 ./P> < P>作为一种更好的实践方法,它将使用包含空格的名称、包含通配符的名称、其他名称的子串名称以及其他更奇怪的拐角情况:

processed_files_list=( file2 file6 )
input_files=( file1 file2 file3 file4 file5 file6 file7 )

# create an associative array with filenames as keys, and a fixed value
declare -A input_files_new=( ) # requires bash 4.0 or later
for f in "${input_files[@]}"; do
  input_files_new[$f]=1
done

# remove keys associated with files you don't want
for f in "${processed_files_list[@]}"; do
  unset "input_files_new[$f]"
done

# Print shell-quoted version of the keys from that associative array.    
printf '%q\n' "${!input_files_new[@]}"

对不起,我最初的回答完全是胡说八道。实际发生的是,在每次调用时,您都将input_files_new的值设置为input_files的值,当前值为$i$输入_文件永远不会更改。所以每次通过循环它都会得到完整的文件list@Cwissy:建议删除原始评论。在此处捕获
echo
的输出毫无意义<代码>对于$processed_文件中的i已足够。欢迎使用SO!感谢您提供了一个小而完整的测试用例以及实际和预期的输出+1像使用列表一样使用字符串。Bash具有真正的数组支持,如果您使用它,您的代码在特殊情况下(例如使用空格或文字换行符处理文件名)的性能会更好。