省略文本中的单词

Omit words in a text

假设我有这个文件 (file.txt):

Hello my name is Giorgio,
I would like to go with you
to the cinema my friend

我想从文本中排除单词:myisI(不是整行)。

单词在文件 (words.txt) 中是这样的:

my
is
I

所以输出必须是:

Hello name Giorgio,
would like to go with you
to the cinema friend

如何执行此操作?

应该这样做:

#!/bin/bash
cp file.txt newfile.txt # we will change newfile.txt in place
while IFS= read -r line;do
[[ $line != "" ]] && sed -i "s/\b$line[[:space:]]*//g" newfile.txt
done <words.txt
cat newfile.txt

或修改@choroba的sed解决方案:

sed 's=^=s/\b=;s=$=[[:space:]]*//g=' words.txt | sed -f- file.txt

以上两者都会从匹配字符串的末尾去除空格(如果有的话)。

输出:

Hello name Giorgio,
would like to go with you
to the cinema friend #There's a space here (after friend)

您可以使用 sed 将 words.txt 变成 sed 脚本:

sed 's=^=s/=;s=$=//g=' words.txt | sed -f- file.txt

与预期输出的区别在于空格:删除单词不会压缩周围的空格。

要仅匹配整个单词,请添加单词边界 \b:

s=^=s/\b=;s=$=\b//g=

同样压缩空格(并且不关心元字符)的 Perl 解决方案:

#!/usr/bin/perl
use warnings;
use strict;

open my $WORDS, '<', 'words.txt' or die $!;
my %words;
chomp, $words{$_} = q() while <$WORDS>;

open my $TEXT, '<', 'file.txt' or die $!;
while (<$TEXT>) {
    s=( ?\b(\S+)\b ?)=$words{} // =ge;
    print;
}

awk 中相当邋遢的版本。如果单词列表包含元字符,那么这 die.It 会考虑单词边界,因此不会在单词中间匹配。

awk 'FNR==NR{a[];next}
     {for(i in a)gsub("(^|[^[:alpha:]])"i"([^[:alpha:]]|$)"," ")}1' {words,file}.txt

Hello name Giorgio,
 would like to go with you
to the cinema friend

它将第一个文件中的单词保存到数组a中。 在保存的每个单词的下一个文件中,它只是使用 alpha(所有字母字符)以及行的开头和结尾从行中删除该单词,以确保该单词是一个完整的单词。 1 打印该行。