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

A C*_*nge 1670 shell sed in-place text-parsing

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

Sie*_*geX 2568

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

sed '/pattern to match/d' ./infile
Run Code Online (Sandbox Code Playgroud)

要直接修改文件:

sed -i '/pattern to match/d' ./infile
Run Code Online (Sandbox Code Playgroud)

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

sed -i '' '/pattern to match/d' ./infile
Run Code Online (Sandbox Code Playgroud)

对于Mac OS X和FreeBSD用户:

sed -i.bak '/pattern to match/d' ./infile
Run Code Online (Sandbox Code Playgroud)

  • @A Clockwork:是的,您需要将输出重定向到一个新文件,例如`sed'/ pattern to match/d'./ example> ./newfile`或者如果你想进行就地编辑然后你可以在`sed -i'/ pattern中添加`-i`标志到sed,以匹配/ d'./ infile`.请注意,`-i`标志需要GNU sed并且不可移植 (110认同)
  • Mac OS X用户的另一个注意事项:由于某种原因,-i标志需要传递一个参数,即使它只是一个空字符串,如`sed -i'''/ pattern/d'./ infile`. (82认同)
  • 对于某些风味的sed; sed的"-i"标志需要提供扩展名.(例如`sed -i.backup'/ pattern to match/d'./ infile`)这让我得到了就地编辑. (16认同)
  • 谢谢,但似乎没有从文件中删除它,只是打印出没有该字符串的文本文件内容. (13认同)
  • @SiegeX更好的是,不要将像`sed`这样的命令应用于任何非版本控制的文件. (8认同)
  • 请注意,如果您的模式将包含正斜杠,则可以使用备用模式分隔符,但必须转义第一个,例如:`sed -i.bak"\#$ pattern_variable_containing_slashes #d"./ infile` (5认同)
  • 我怎么知道我有什么版本的 sed?GNU 还是非 GNU? (2认同)
  • @AishwaryaKulkarni您将用'$'锚定比赛,如'/ pattern以E1 $ /'结尾 (2认同)
  • 想要编辑 ENORMOUS 文件的人请注意: sed 确实会写一个临时文件。它并不是真正的“到位”。如果您没有足够的磁盘空间,您将 a) 磁盘空间不足 b) 必须手动删除临时文件。 (2认同)

kur*_*umi 603

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

AWK

awk '!/pattern/' file > temp && mv temp file
Run Code Online (Sandbox Code Playgroud)

Ruby(1.9+)

ruby -i.bak -ne 'print if not /test/' file
Run Code Online (Sandbox Code Playgroud)

Perl的

perl -ni.bak -e "print unless /pattern/" file
Run Code Online (Sandbox Code Playgroud)

Shell(bash 3.2及更高版本)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
Run Code Online (Sandbox Code Playgroud)

GNU grep

grep -v "pattern" file > temp && mv temp file
Run Code Online (Sandbox Code Playgroud)

当然sed(打印反转比实际删除更快):

sed -n '/pattern/!p' file
Run Code Online (Sandbox Code Playgroud)

  • `sed`示例有不同的行为,它只有greps!它应该像`sed -n -i'/ pattern /!p'file`. (10认同)
  • 当每一行与模式匹配时,grep版本不起作用.更好:`grep -v"pattern"file> temp; mv temp file`这可能适用于其他一些示例,具体取决于返回值. (8认同)
  • 如何删除具有模式的特定行以及紧邻其上方的行?我在不同的数据之间有数千条这样的线路. (4认同)
  • “打印反向比实际删除快” - 不在我的机器上(2012 MacBook Air,OS X 10.13.2)。创建文件:`seq -f %f 10000000 &gt;foo.txt`。sed d: `time sed -i '' '/6543210/d' foo.txt` 实数 0m9.294s。sed !p: `time sed -i '' -n '/6543210/!p' foo.txt` 实数 0m13.671s。(对于较小的文件,差异较大。) (3认同)
  • 在 OS/X 上,shell 变体不保留前导空格,但 grep -v 变体对我来说效果很好。 (2认同)

sla*_*tir 237

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

例如

sed -i '/pattern/d' filename      
Run Code Online (Sandbox Code Playgroud)

要么

grep -v "pattern" filename > filename2; mv filename2 filename
Run Code Online (Sandbox Code Playgroud)

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

  • 只是因为你尝试了性能比较而投票给你答案! (19认同)
  • (使用ubuntu的/ usr/share/dict/words)grep和mv:0.010s | sed到位:0.197s | sed和mv:0.031s (7认同)
  • +1用于提供使用grep行覆盖当前文件的选项. (4认同)
  • 我很好奇,如果它是'sed'/ pattern/d'filename> filename2,性能差异是多少; mv filename2 filename` (3认同)
  • 第二个'grep'解决方案对于大文件也更好 (2认同)

Kev*_*yen 68

使用GNU的简单方法sed:

sed --in-place '/some string here/d' yourfile
Run Code Online (Sandbox Code Playgroud)

  • 对于偶然发现这个Q&A线程并且是shell脚本新手的其他人来说,这是一个方便的提示:短命令适用于命令行上的一次性使用,但是在脚本中应该首选长选项,因为它们更具可读性. (45认同)
  • 请注意,long选项仅适用于GNU sed.Mac和BSD用户需要安装gsed才能这样做. (8认同)
  • +1 --in-place标志。我需要在权限保护的文件上进行测试。(必须进行一些用户擦洗。) (3认同)
  • 另一个提示:如果您的正则表达式似乎不匹配,请尝试“-r”选项(或“-E”,具体取决于您的版本)。这使得可以使用正则表达式元字符“+”、“?”、“{...}”和“(...)”。 (2认同)

ken*_*orb 34

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

ex +g/match/d -cwq file
Run Code Online (Sandbox Code Playgroud)

哪里:

  • +执行Ex命令(man ex),-c执行相同wq(写入和退出)
  • g/match/d- 删除给定行的Ex命令match,参见:g的幂

上面的示例是一个POSIX兼容的方法,用于根据Unix.SEPOSIX规范中的ex这篇文章就地编辑文件.


不同之sed处在于:

sed是一个S tream ED itor ,而不是文件编辑器.BashFAQ

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

  • 那很棒...当我做'man ex`时,它给了我'vim`的人,似乎`ex`是vim的一部分...如果我理解正确,那就意味着`match`的模式语法是http: //vimregex.com/与POSIX和PCRE风味相似但不同? (4认同)

Ani*_*nha 16

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

所以我用过:

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

哪里$file是需要删除的文件,是$pattern要匹配删除的模式.

''从这个评论中选择了.

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

  • Mac`sed'在`-i`之后需要一个参数,所以如果你不想备份,你仍然需要添加一个空字符串:`-i''` (3认同)
  • 对于 shell,请使用 `sed -i "/$pattern/d" $file` 。谢谢您的回答。 (2认同)

djp*_*lta 16

从所有文件中删除匹配的行

grep -rl 'text_to_search' . | xargs sed -i '/text_to_search/d'
Run Code Online (Sandbox Code Playgroud)


Jad*_*zia 14

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

无论有没有设置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
Run Code Online (Sandbox Code Playgroud)


Bhu*_*esh 12

你也可以用这个:

 grep -v 'pattern' filename
Run Code Online (Sandbox Code Playgroud)

这里-v只打印您的图案以外的其他图案(表示反转匹配).


Jah*_*hid 12

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

echo "$(grep -v "pattern" filename)" >filename
Run Code Online (Sandbox Code Playgroud)

  • 这只适用于`bash` shell或类似的(不是`tcsh`). (4认同)

小智 7

您还可以删除文件中的一系列行。例如删除 SQL 文件中的存储过程。

sed '/CREATE PROCEDURE.*/,/END ;/d' sqllines.sql

这将删除 CREATE PROCEDURE 和 END ; 之间的所有行。

我已经用这个 sed 命令清理了许多 sql 文件。


Kje*_* S. 5

perl -i    -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Run Code Online (Sandbox Code Playgroud)

第一个命令就地编辑文件 (-i)。

第二个命令执行相同的操作,但通过将 .bk 添加到文件名(.bk 可以更改为任何内容)来保留原始文件的副本或备份。