我有一个日志文件,其大小开始增长,我需要从中删除某些与给定模式匹配的行。我使用grep -nr
来提取目标行并将它们复制到临时文件中,但我无法确定如何告诉sed
从日志文件中删除这些行。
我在这里找到了类似的东西:Delete line from text file with line numbers from another file但是这并没有实际删除这些行,它只打印想要的输出。
任何人都可以给我一个提示吗?
谢谢!
答案 0 :(得分:3)
我认为,你真正需要的是sed -i '/pattern/d' filename
。
但要回答你的问题:
如何删除与另一个文件中的行号匹配的行:
(假设line_numbers文件中没有特殊字符,每行只有一个数字......)
awk 'NR==FNR{a[$0]=1; next}; !(FNR in a)' line_numbers input.log
答案 1 :(得分:1)
如果您已经有了打印标准输出的方法,那么就没有理由不能覆盖原始文件。例如,要仅打印与模式不匹配的行,可以使用:
grep -v 'pattern' original > tmp && mv tmp original
这会将grep
命令的输出重定向到临时文件,然后覆盖原始文件。毕竟,“就地”这样做的任何其他解决方案都只是假装这样做。
使用sed as suggested in the comments或awk:
还有很多其他方法可以做到这一点awk '!/pattern/' original > tmp && mv tmp original
答案 2 :(得分:0)
如果您想使用sed
并且文件不断增长,则必须更频繁地执行sed -i '/REGEX/d' FILENAME
。
相反,您可以使用syslog-ng
。您只需编辑/etc/syslog-ng/syslog-ng.conf
,其中您需要创建/编辑适当的过滤器(有点像:f_example { not match(REGEX); };
),保存文件,重新启动服务,您就完成了。
包含该特定模式的消息不会转储到日志文件中。通过这种方式,您的文件不仅会停止增长,而且还无需使用sed
或grep
定期处理。
答案 3 :(得分:0)
要删除带有sed的行,您可以执行以下操作:
sed "${line}d" <originalLogF >tmpF
如果要删除多行,可以传递一个sed脚本。在这里,我删除了第一行和第二行:
sed '1d;2d' <originalLogF >tmpF
如果你的日志文件很大,你可能有两次通过。第一个在文件中生成sed脚本,第二个用于应用sed脚本。但是如果你能够直接识别模式(并且根本不使用“$ {line} d”),那么只有一次传递会更有效。看Tom Fenech或anishsane的答案,我认为这是你真正需要的。
顺便说一下,你必须保留inode(不仅是文件名),因为大多数记录器都会保持文件打开。所以最后的命令(如果你不使用sed -i)应该是:
cat tmpF >originalLogF
顺便说一句,“-i”选项(sed)不是魔法,sed会创建一个临时缓冲区,所以如果我们有并发追加到日志文件,你可以松开一些行。