grep 查找文件中的一行,然后删除该行

问题描述 投票:0回答:3
$ cat example.txt

产量:

example
test
example

我想从此文件中删除“test”字符串。

$ grep -v test example.txt > example.txt 
$ cat example.txt 
$

下面的方法可行,但我感觉有更好的方法!

$ grep -v test example.txt > example.txt.tmp;mv example.txt.tmp example.txt 
$ cat example.txt 
example
example

值得注意的是,这将位于一个超过 10,000 行的文件中。

干杯

string bash awk sed grep
3个回答
20
投票

你可以使用 sed,

sed -i '/test/d' example.txt

-i
保存对该文件所做的更改。所以你不需要使用重定向运算符。

-i[SUFFIX], --in-place[=SUFFIX]
             edit files in place (makes backup if SUFFIX supplied)

17
投票

你的做法是正确的,但在 mv 之前使用

&&
以确保 grep 成功,否则你将删除原始文件:

grep -F -v test example.txt > example.txt.tmp && mv example.txt.tmp example.txt

我还添加了

-F
选项,因为您说要删除字符串,而不是正则表达式。

您可以使用

sed -i
但是您需要担心找出和/或转义 sed 分隔符,并且 sed 不支持搜索字符串,因此您需要尝试转义搜索字符串中正则表达式字符的所有可能组合尝试让 sed 将它们视为文字字符(由于正则表达式字符的位置敏感性质,您无法自动化这一过程),它所节省的只是手动命名您的 tmp 文件,因为 sed 无论如何在内部使用一个文件。

哦,另一种选择 - 您可以使用带有“就地编辑”功能的 GNU awk 4.*。它也像 sed 一样在内部使用 tmp 文件,但它确实支持字符串操作,因此您不需要尝试转义 RE 元字符,并且它没有分隔符作为语法的一部分而需要担心:

awk -i inplace -v rmv="test" '!index($0,rmv)' example.txt

任何 grep/sed/awk 解决方案都会在眨眼间运行 10,000 行文件。


0
投票

您的

grep
命令将立即导致输出文件 (
example.txt
) 打开以进行写入。这会删除(“截断”)文件的内容,因此文件在开始读取时为空。

moreutils

 包中的 
sponge 命令专为此类情况而设计,例如

grep -v test example.txt | sponge example.txt
这是有效的,因为

sponge

将缓冲其所有输入,并且仅在完成接收输入后才打开给定文件(
example.txt
)进行写入。请注意,对于大于 RAM 的文件来说,这可能不是一个好主意!

Moreutils 在大多数发行版中都可用。

© www.soinside.com 2019 - 2024. All rights reserved.