我该如何使用sed删除一个文本文件中包含特定字符串的所有行?
我该如何使用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 '!/pattern/' file > temp && mv temp file
ruby -i.bak -ne 'print if not /test/' file
perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
grep -v "pattern" file > temp && mv temp file
当然还有 sed
(打印反向文本比实际删除更快):
sed -n '/pattern/!p' file
grep -v
变量对我非常有效。 - Paul Beusteriensed
的例子有不同的行为,它只是查找匹配内容!应该改成类似这样的命令:sed -n -i '/pattern/!p' file
。请注意,这个命令只会保留不匹配模式的行,并在原文件上进行修改。 - caesarsolgrep -v "pattern" file > temp; mv temp file
根据返回值情况,这个做法可能也适用于其他示例。 - Chris Maesseq -f %f 10000000 >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。(对于较小的文件,差异更大。) - jcsahnwaldt Reinstate Monicased -i '/pattern/d' filename
或者
grep -v "pattern" filename > filename2; mv filename2 filename
无论如何,在我的机器上第一个命令需要3倍的时间。
sed '/pattern/d' filename > filename2; mv filename2 filename
会有什么性能差异。 - Pete使用GNU sed
的简易方法:
sed --in-place '/some string here/d' yourfile
-r
选项(或-E
,具体取决于您的版本)。这将启用正则表达式元字符+
、?
、{...}
和(...)
的使用。 - rjh你可以考虑使用ex
(一种基于标准Unix命令的编辑器):
ex +g/match/d -cwq file
其中:
+
执行给定的 Ex 命令(man ex
),与执行 wq
(写入并退出)的 -c
相同g/match/d
- 用于删除带有给定 match
的行的 Ex 命令,参见:Power of g上面的示例是一种符合 POSIX 标准的方法,用于原地编辑文件,具体请参见 Unix.SE 上的帖子和ex 的 POSIX 规范。
与 sed
的区别在于:
sed
是一个流编辑器,而不是一个文件编辑器。BashFAQ
除非您喜欢不可移植的代码、I/O 开销和其他一些副作用。因此,一些参数(例如原地编辑/-i
)是非标准的 FreeBSD 扩展,可能在其他操作系统上不可用。
man ex
时,显示的是 vim
的说明文档,看来 ex
是 vim
的一部分。如果我理解正确的话,这意味着 match
的模式语法应该是 http://vimregex.com/,它与 POSIX 和 PCRE 风格有些相似但也有所不同? - Anentropicex
使用临时文件,就像每个其他正常的工具一样,除了可能使用dd
。 - CervEd我在Mac上遇到了问题。而且,我需要使用变量替换来完成它。
所以我使用了:
sed -i '' "/$pattern/d" $file
其中$file
是需要删除的文件,$pattern
是要匹配删除的模式。
我从这个评论中选择了''
。
需要注意的是在"/$pattern/d"
中使用双引号。如果使用单引号,则变量将不起作用。
sed
命令在使用-i
选项时需要加上一个参数。因此,如果你不想备份原始文件,仍需添加一个空字符串:-i ''
。 - wisbuckysed -i "/$pattern/d" $file
。谢谢您的回答。 - Ashwaq您也可以使用这个:
grep -v 'pattern' filename
这里的-v
参数将只打印除了匹配模式之外的内容(也就是反向匹配)。
要使用grep
获得类似于inplace的结果,您可以这样做:
echo "$(grep -v "pattern" filename)" >filename
bash
或类似的 shell(不适用于 tcsh
)。 - esmit我用一份大约有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
删除所有匹配的文件中的行
grep -rl 'text_to_search' . | xargs sed -i '/text_to_search/d'
sed -i.bak "/str/d" ./infile
命令会删除整个文件。 - chovysed -i.bak "\#$pattern_variable_containing_slashes#d" ./infile
。 - Eric