循环遍历数组并使用grep删除匹配模式



我有一个数组

array=("Tom" "Mango" "Boy")

和包含

内容的文件
Tom
Mango
Jam
Boy
Girl
Dog
Cat

我想从数组中删除匹配的元素,并将它们写入文件。

我尝试使用for循环

for t in ${array[@]}; do grep -v "$t" "file.txt" >> "file.txt.tmp";done

然而,这并没有像预期的那样工作。它每次接受一个参数,并写入被排除的内容,从而产生重复:


Mango
Jam
Boy
Girl
Dog
Cat
Tom
Jam
Boy
Girl
Dog
Cat
Tom
Mango
Jam
Girl
Dog
Cat

我想在一次移除所有匹配元素的情况下生成file.txt.tmp。我希望


Jam
Girl
Dog
Cat

是否有办法做到这一点与for循环和grep。我知道我可以在grep中使用|分隔的多个模式,但我不确定如何使用循环数组元素。

不幸的是,sed不会为我工作,因为我试图删除包含模式ie的一部分的整行。如果有一行

Tom speaks和输入模式是Tom,我想要删除整个行。grep -v似乎是最简单的方法。

我知道我可以在grep中使用由|分隔的多个模式,但我不确定如何使用它并循环数组元素。

您可以使用命令替换和IFS来格式化数组,例如:

#!/usr/bin/env bash
array=("Tom" "Mango" "Boy")
pattern=$(IFS='|'; printf '%s' "${array[*]}")
grep -Ev "$pattern" file.txt

输出
Jam
Girl
Dog
Cat

检查变量pattern的值,

declare -p pattern

输出
declare -- pattern="Tom|Mango|Boy"

或者只是,

array=("Tom" "Mango" "Boy")
grep -Fxv "$(printf '%sn' "${array[@]}")" file.txt

  • 查看我如何获得所有行:在两个文件中设置交集)或仅在两个文件中的一个(设置减法)

可以将它们写入文件。

$: printf "%sn" "${array[@]}" > patfile
$: grep -vf patfile fullfile
Jam
Girl
Dog
Cat

Jetchisel的解决方案可能更好,除非你的列表足够大,使你的系统或配置的限制,如命令行长度,或参数限制。

这两种情况现在都不太可能发生,但也许您使用的是旧系统,或者您的系统管理员过于苛刻。如果发生这种情况,您可能不得不使用一个文件,并使用for循环而不是printf "%sn" "${array[@]}"

你的大部分问题是执行grep多次。每次运行它时(所有的时间和开销会在任何更大的任务中真正增加),您都会拉出与这个参数不匹配的每一行,这就是为什么您会得到重复值。您必须将排除项合并到一个模式或一个文件中,这样您就可以一次完成。

相关内容

  • 没有找到相关文章

最新更新