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


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


1324
2018-03-23 19:46


起源




答案:


要删除该行并将输出打印到标准输出:

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

要直接修改文件:

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

要直接修改文件(并创建备份):

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

对于Mac OS X用户:

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

1988
2018-03-23 19:48



谢谢,但它似乎没有从文件中删除它,只是打印出没有该字符串的文本文件内容。 - A Clockwork Orange
@A发条:是的,你需要将输出重定向到一个类似的新文件 sed '/pattern to match/d' ./infile > ./newfile 或者如果你想进行就地编辑,那么你可以添加 -i标志为sed,如 sed -i '/pattern to match/d' ./infile。请注意 -i flag需要GNU sed并且不可移植 - SiegeX
对于某些风味的sed; sed的“-i”标志需要提供扩展名。 (例如。 sed -i.backup '/pattern to match/d' ./infile这让我得到了就地编辑。 - avelis
@SiegeX更好的是,不要应用像这样的命令 sed 任何不受版本控制的文件。 - MatrixFrog
Mac OS X用户的另一个注意事项:由于某种原因,-i标志需要传递参数,即使它只是一个空字符串,如 sed -i '' '/pattern/d' ./infile。 - geerlingguy


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

AWK

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

Ruby(1.9+)

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

Perl的

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

壳牌(bash3.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 

525
2018-03-23 23:57



+1完整性! - Adri C.S.
如何删除具有模式的特定行以及紧邻其上方的行?我在不同的数据之间有数千条这样的线路。 - oortcloud_domicile
在OS / X上,shell变体不保留前导空格,但grep -v变体对我来说效果很好。 - Paul Beusterien
该 sed 例子有不同的行为,它只有greps!它应该是这样的 sed -n -i '/pattern/!p' file。 - caesarsol
当每一行与模式匹配时,grep版本不起作用。更好: grep -v "pattern" file > temp; mv temp file 这可能适用于其他一些示例,具体取决于返回值。 - Chris Maes


您可以使用sed替换文件中的行。但是,它似乎比使用grep将逆转换为第二个文件然后将第二个文件移动到原始文件上要慢得多。

例如

sed -i '/pattern/d' filename      

要么

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

无论如何,第一个命令在我的机器上花了3倍的时间。


188
2017-11-02 02:37



只是因为你尝试了性能比较而投票给你答案! - anuragw
+1用于提供使用grep行覆盖当前文件的选项。 - Rhyuk
第二个'grep'解决方案对于大文件也更好 - simoes
我很好奇,如果它有什么性能差异 sed '/pattern/d' filename > filename2; mv filename2 filename - Pete
(使用ubuntu的/ usr / share / dict / words)grep和mv:0.010s | sed到位:0.197s | sed和mv:0.031s - ReactiveRaven


使用GNU的简单方法 sed

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

51
2018-01-02 17:56



对于偶然发现此Q&A线程并且不熟悉shell脚本的其他人来说,这是一个方便的提示:短命令可以在命令行上进行一次性使用,但是在脚本中应该首选长选项,因为它们更具可读性。 - Dennis
+1为--in-place标志。我需要测试权限受保护的文件。 (必须做一些用户擦洗。) - Bee Kay
请注意,long选项仅适用于GNU sed。 Mac和BSD用户需要安装gsed才能这样做。 - Matt


你可以考虑使用 ex (这是一个标准的基于UNIX命令的编辑器):

ex +g/match/d -cwq file

哪里:

  • + 执行给定的Ex命令(man ex), 与...一样 -c 执行 wq (写和退出)
  • g/match/d  - Ex命令删除给定的行 match,见: g的力量

上面的示例是符合POSIX标准的方法,用于就地编辑文件 在Unix.SE上发帖 和 POSIX规范 ex


与...的区别 sed 就是它:

sed 是一个 小号tream EDitor,而不是文件编辑器。BashFAQ

除非你喜欢不可移植的代码,I / O开销和一些其他不良副作用。所以基本上是一些参数(比如就地/-i)是非标准的FreeBSD扩展,可能在其他操作系统上不可用。


25
2017-10-17 11:54



那太好了...当我这样做的时候 man ex 它给了我这个男人 vim, 它似乎 ex 是vim的一部分......如果我理解正确,那意味着模式语法 match 是 vimregex.com 这与POSIX和PCRE风味相似但不同? - Anentropic
:g  是 POSIX兼容 命令与一些 细微差别。我假设PCRE是基于它的。 - kenorb


我在Mac上遇到了这个问题。另外,我需要使用变量替换来完成它。 所以我用过:

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

哪里 $file 是需要删除的文件 $pattern 是要删除的匹配模式。 挑了 '' 由此 评论。 这里要注意的是使用 双引号 在 "/$pattern/d"。当我们使用单引号时,变量将不起作用。


13
2018-03-09 15:39



苹果电脑 sed 之后需要一个参数 -i,所以如果你不想要备份,你仍然需要添加一个空字符串: -i '' - wisbucky


为了得到一个类似于结果的地方 grep 你可以这样做:

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

12
2018-06-13 19:24



这只适合 bash 壳或类似物(不是 tcsh)。 - esmit


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

无论有没有设置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

10
2018-03-19 12:45



你在哪个平台?你使用哪个版本的sed / perl / grep? - hagello
我使用的平台是Linux(Gentoo)。 sed版本是GNU sed v 4.2.2,perl版本perl 5(我不能告诉我在测试时使用的是哪个版本),而grep(GNU)是版本3.0。 - Jadzia