删除文本文件中包含特定字符串的行

我将如何使用 sed 删除文本文件中包含特定字符串的所有行?

答案

要删除行并将输出打印到标准输出,请执行以下操作:

sed '/pattern to match/d' ./infile

要直接修改文件–不适用于 BSD sed:

sed -i '/pattern to match/d' ./infile

相同,但是对于 BSD sed(Mac OS X 和 FreeBSD)–不适用于 GNU sed:

sed -i '' '/pattern to match/d' ./infile

要直接修改文件(并创建备份)–与 BSD 和 GNU sed 一起使用:

sed -i.bak '/pattern to match/d' ./infile

sed外,还有许多其他方法可以删除具有特定字符串的行:

AWK

awk '!/pattern/' file > temp && mv temp file

红宝石(1.9+)

ruby -i.bak -ne 'print if not /test/' file

佩尔

perl -ni.bak -e "print unless /pattern/" file

Shell(bash 3.2 及更高版本)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

GNU grep

grep -v "pattern" file > temp && mv temp file

当然是sed (打印反色比实际删除要快):

sed -n '/pattern/!p' file

您可以使用 sed 替换文件中的行。但是,这似乎比使用 grep 取反将其慢进第二个文件,然后将第二个文件移到原始文件上要慢得多。

例如

sed -i '/pattern/d' filename

要么

grep -v "pattern" filename > filename2; mv filename2 filename

无论如何,第一个命令在我的计算机上花费的时间要长 3 倍。

使用 GNU sed的简单方法:

sed --in-place '/some string here/d' yourfile

您可以考虑使用ex (这是标准的基于 Unix 命令的编辑器):

ex +g/match/d -cwq file

哪里:

  • +执行给定的 Ex 命令( man ex ),与-c执行wq (写并退出)
  • g/match/d Ex 命令删除具有给定match ,请参阅: g 的幂

上面的示例是 POSIX 兼容方法,用于按照 Unix.SE 上的这篇文章ex POSIX 规范就地编辑文件。


sed的区别在于:

sedS tream ED监视器,而不是文件编辑器。 Bash 常见问题

除非您喜欢不可移植的代码,否则 I / O 开销和其他一些不良影响。因此,基本上,某些参数(例如 in-place / -i )是非标准的 FreeBSD 扩展,在其他操作系统上可能不可用。

我在 Mac 上为此苦苦挣扎。另外,我需要使用变量替换来做到这一点。

所以我用了:

sed -i '' "/$pattern/d" $file

其中$file是需要删除的文件, $pattern是要匹配的删除模式。

我从此评论中选择了''

这里要注意的是在"/$pattern/d"使用双引号 。当我们使用单引号时,变量将不起作用。

您还可以使用以下命令:

grep -v 'pattern' filename

在这里-v将仅打印您的模式以外的其他内容(这意味着反转匹配)。

我用一个包含大约 345 000 行的文件做了一个小的基准测试。在这种情况下,使用grep的方法似乎比sed方法快 15 倍左右。

我尝试过在设置 LC_ALL = C 和不设置 LC_ALL = C 的情况下,似乎都不会明显改变计时。搜索字符串(CDGA_00004.pdbqt.gz.tar)在文件中间。

以下是命令和时间:

time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt

real    0m0.711s
user    0m0.179s
sys     0m0.530s

time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt

real    0m0.105s
user    0m0.088s
sys     0m0.016s

time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )

real    0m0.046s
user    0m0.014s
sys     0m0.019s

要使用grep获得类似结果的结果,您可以执行以下操作:

echo "$(grep -v "pattern" filename)" >filename