使用for循环删除不匹配的单词?

时间:2016-03-27 11:23:16

标签: shell

假设我有一个名为animals的变量,它存储以下单词。

cat
dog
bird
whale

我还有另一个名为delete的变量,其中包含一个或多个正则表达式,我将用它来删除列表中的某些动物。

如果删除变量只包含一个正则表达式,请说bird$并输入

echo "$animals" | sed "/$delete/!d"

然后在动物变量中留下的确实只是鸟类这个词。

当我想删除多个动物时出现问题,这意味着我的删除变量中有两个或更多个正则表达式(由空格分隔)。

让我们说删除变量no包含:dog $ bird $。

我已经写了这个for循环:

for i in $delete; do
 animals=$(echo "$animals" | sed "/$i/!d")
done

但这不起作用。我认为它给了我一个完全空的动物变量。

相反的是:sed“/ $ i / d”有效。

如何删除与正则表达式不匹配的模式?

感谢。

2 个答案:

答案 0 :(得分:1)

如果您将delete变量的格式从分隔为|(管道)的空格分开(在正则表达式语法中表示OR),则可以在一次扫描中完成:

animals="cat
dog
bird
whale"

delete='dog$|bird$'
echo "$animals" | sed -r "/$delete/"'! d'
dog
bird
  • 请注意双引号和单引号的引用,因为双引号内的!的bash解释

答案 1 :(得分:0)

您无法逐个浏览列表,因为每个字都无法匹配其中一个模式并被删除。

在决定是否删除单词之前,您需要同时测试所有模式。一种方法是使用awk:

awk -v d="$delete" 'BEGIN { n = split(d, patterns) } 
{ for (i = 1; i <= n; ++i) if ($0 ~ patterns[i]) { print; next } }' animals

在处理文件之前,我们将空格分隔的模式列表拆分为数组。对于文件的每一行,我们遍历列表并打印与其中一个模式匹配的任何行。