![要从文件中删除的模式列表](https://linux22.com/image/895925/%E8%A6%81%E4%BB%8E%E6%96%87%E4%BB%B6%E4%B8%AD%E5%88%A0%E9%99%A4%E7%9A%84%E6%A8%A1%E5%BC%8F%E5%88%97%E8%A1%A8.png)
为了进一步说明,我们有两个文件内容:
文件1
hello
1_hello
2_hello
world
1_world
2_world
hello1
1_hello1
2_hello1
world1
1_world1
2_world1
文件2
This
hello
1_hello
2_hello
is world
1_world
2_world
my
hello1
1_hello1
2_hello1
word
world1
1_world1
2_world1
file
我想要的是迭代文件 1 的第一列并删除文件 2 中匹配的条目并产生如下输出:
This
is
my
word
file
我该怎么办?
答案1
你想使用 awk 读取 file1 并记住其中的所有单词。然后读取 file2 并输出 file1 中未见过的任何单词:
gawk -v RS='[[:space:]]+' 'NR==FNR {words[$1]=1; next} !($1 in words)' file1 file2
它使用任意空格序列作为记录分隔符,因此每个单词都被视为单独的“行”。这现在是 GNU awk 特有的,但这是 Ubuntu 上的默认 awk
答案2
您可以使用grep -f FILE
从文件中获取模式FILE
。对于您的情况,我建议在以下最终grep
调用中使用一些附加标志(请参阅下面的说明):
grep -v -x -F -f file1 -- file2
-f FILE
– 从中获取模式FILE
,每行一个。-F
– 将模式解释为固定字符串列表,以换行符分隔,其中任何一个都可以匹配。-x
– 仅选择与整行完全匹配的匹配项。(如果您想允许部分匹配的行,则可能需要删除此选项。)-v
– 反转匹配的方向,以选择不匹配的线。
资料来源:GNU grep 文档或者手册页
上面使用的所有选项均由 POSIX 指定,不需要 GNU 扩展。
答案3
这个命令行应该可以解决问题:
while read -r word; do sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; done < file1
执行上述命令后,输出文件——file2
应该如下所示:
This
is
my
word
file
上述命令行的更易读的版本:
while read -r word; do \
sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; \
done < file1
循环while
逐行读取文件 - < file1
。每行的值用作临时创建的变量的值,称为$word
- -r word
。此变量用作命令中的参数,并在 [ ] 中用空白值sed
替换,即第一个表达式:= 。标志表示 - 将替换应用于所有匹配项。然后,如果文件中有空白行,则会将其删除 - 第二个表达式:。s
file2
"s/\<$word\>//g"
s/<source_value>/<replacement_value>/g
g
'/^\s*$/d'
我们需要使用语法来查找精确匹配。第一个表达式\<...\>
需要双引号 - - ,因为它是变量的名称,我们希望在命令中将其扩展为其值。"..."
$word
sed
选项-i
表示更改将在目标文件内进行 - file2
。如果删除此选项,结果将抛出到 stdout,但这没有任何意义。此选项-i.bak
不适用于这种情况,因为目标文件将被多次覆盖,因此您应该提前创建备份副本。
答案4
虽然删除标准不是很清楚,但我假设要删除的部分是(www\n1_www\n2_www
)对于所有单词www
(如果我错了,请纠正我)
使用(gnu)sed:
sed -zr 's/(\w+)\n1_\1\n2_\1\n//g' ex