grep 从行中删除完全匹配而不删除整行

grep remove exact matches from line without removing the whole line

我有 patterns.txt 个文件,我想从 FILE.txt 中删除所有完全匹配的模式。 FILE.txt 如下:

word1 word2
word3 word4
word5 word6

模式文件包含:

word1
word6

预期输出为:

word2
word3 word4
word5

下面的命令删除了完全匹配的整行。如何只从一行中删除完全匹配而不删除整行?我不想使用 for 循环来实现这一点。

cat FILE.txt | grep -wvf pattern.txt

你可以试试这个awk:

awk 'FNR == NR {pats[]; next} {more=0; for (i=1; i<=NF; ++i) if (!($i in pats)) printf "%s", (more++ ? OFS : "") $i; print ""}' patterns.txt file

word2
word3 word4
word5

更具可读性的版本:

awk '
FNR == NR {
   pats[]
   next
}
{
   more = 0
   for (i=1; i<=NF; ++i)
      if (!($i in pats))
         printf "%s", (more++ ? OFS : "") $i
   print ""
}' patterns.txt file

为了以单词(字符串)作为分隔符来分割文本,可以使用awk。

awk -F 'word' '{print ;print }' file.txt

如果您只想显示定界符之后的内容,那么它将是:

awk -F 'word' '{print }' file.txt

为了连续更改模式,您可能需要创建一个循环。

使用 sed:

re=$(tr '\n' '|' < patterns.txt)
sed -r "s/$re//; s/^[[:space:]]*//" file
word2
word3 word4
word5 

注意:确保 patterns.txt 没有尾随换行或额外的换行,因为 | 将在每个位置结束。

我的第一个想法就是做 。然后我认为 perl 可能对此有好处:perl 具有过滤列表的良好功能。问题是 perl 没有 FNR 变量。但我玩弄 a2p 并想出了这个:

perl -lane '
    $FNR = $. - $FNRbase;
    if ($. == $FNR) {
      $ignore{$F[0]} = 1;
    } else {
      print join " ", grep {not exists $ignore{$_}} @F;
    }
  } continue {
    $FNRbase = $. if eof
' pattern.txt FILE.txt