用于从大型日志文件中删除文本和二进制文件摘录的 Shell 脚本或命令

用于从大型日志文件中删除文本和二进制文件摘录的 Shell 脚本或命令

我需要从每天生成的大型日志文件中删除大型二进制文件(PDF 文件)。这严重占用了我们服务器上的空间。我需要从日志中删除大型 PDF,以使日志更小且易于管理

我需要取出字符串之间的文本(或二进制文件)

  • <my:PDF></my:PDF>
  • <applicationForm></applicationForm>
  • <image></image>
  • <extractedSignature></extractedSignature>

我不确定 sed 实用程序是否可以执行此操作,这些文件很大,需要修剪。我不是在寻求日志轮换建议,只是寻求一个脚本或命令,可以删除上面字符之间的这些大文本日志。我不知道该怎么做。这些文件相当大。我不知道如何使用 sed 、 tail 、 head 、 tr 或任何其他工具来实现这一点。

答案1

听起来您的日志文件实际上是 XML 格式。如果是这样的话,那么你该怎么办真的应该做的是使用 XML 解析器。读这个著名的 StackOverflow 答案如果您想了解更多信息。

根据您的描述,基于 SAX 的解析器可能是您最好的选择:这些是面向流的解析器,不需要您将整个文件加载到内存中。由于您只对 XML 执行非常简单的转换,因此 XSLT 可能是一个非常好的候选者(如果您使用,它应该是快速的)xsltproclibxslt)。这是一个展示潜在相关技术的 SO 答案

答案2

start如果 / / 和 / / 模式之间有多行,end则可以使用范围 和d

一般来说

/start/,/end/d

将删除 //start和 //之间的所有行end(含)。

创建一个文件并添加以下行,然后将其另存为 somefile

/<\"my:PDF\">/,/<\"\/my:PDF\">/d
/<\"applicationForm\">/,/<\"\/applicationForm\">/d
/<\"image\">/,/<\"\/image\">/d
/<\"extractedSignature\">/,/<\"\/extractedSignature\">/d

然后像这样使用它

sed -f somefile logfile >prunedfile

答案3

您应该能够使用 sed 执行类似的操作:

cat LOG | sed -e "s/<\"my:PDF\">.*<\/\"my:PDF\">/<\"my:PDF\"><\/\"my:PDF\">/g;" > LOGx

本质上,这表示“查找模式<"my:PDF">,后跟任意数量的任何字符,后跟模式</"my:PDF">并将其替换为模式<"my:PDF"></"my:PDF">,在全局范围内执行此操作”。

根据需要对需要替换的其他字符串重复此操作。

答案4

编辑活动日志既棘手又危险,因此您必须等到它们停止服务。如果这是不可能的,您可能需要检查您的日志记录程序是否可以将输出传递到过滤器而不是写入文件。然后,过滤器可以在信息写入磁盘之前去除不需要的条目。这有点风险更大,因为过滤器死亡日志条目将会丢失。

遗憾的是 sed 正则表达式是“贪婪的”。如果单个日志行有两个或多个您想要删除的字段,sed 将删除之间的所有内容:

<"my:PDF">.*?<"/my:PDF"><"keeper">.*?<"/keeper"><"my:PDF">.*?<"/my:PDF">

使用 -p 选项(参见 man perlrun),perl 的行为可以与 sed 非常相似,但能够请求非贪婪的正则表达式(*? 中的 ?):

perl -p -e '\
    s|<"my:PDF">.*?<"/my:PDF">||g; \
    s|<"applicationForm">.*?<"/applicationForm">||g; \
    s|<"图片">.*?<"/图片">||g; \
    s|<"extractedSignature">.*?<"/extractedSignature">||g; \
           ' 巨大的.log >巨大的.log~ && \
mv 巨大.log~ 巨大.log

相关内容