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