我有一个CGI脚本,我们的员工使用这个脚本从他们无法直接访问的服务器中获取日志。由于我不能进入的原因,在最近更新我们的应用程序之后,这些日志中的一些现在具有诸如换行符,制表符,反斜杠等字符,这些字符被翻译成它们的文本等价物。因此,我修改了CGI脚本以调用以下内容将它们转换回原始值:
perl -i -pe 's/\\r/\r/g && s/\\n/\n/g && s/\\t/\t/g && s/\\\//\//g' $filename
我刚刚获悉有些人在尝试获取相当大的日志(几百MB)时会出现内存不足错误。
我的问题:当调用这样的内联命令时,perl如何管理内存?是读取整个文件,处理它,然后写出来,还是创建一个临时文件,一次处理输入文件中的行,然后一旦完成就替换文件?
这是在64位Amazon Linux实例上使用perl 5.10.1。
答案 0 :(得分:2)
-p
开关创建一个while(<>){...; print}
循环来迭代输入文件中的每个“行”。
如果您的所有换行都已转换为"\\n"
,那么您的文件将只是一条很长的行。因此,您的命令将整个文件加载到内存中以执行修复。
为避免这种情况,您必须使用sysread
或$/
故意缓冲文件。
最简单的方法是创建一个实际的脚本而不是单行来完成工作。但是,如果您知道所有换行都已转换,那么一个简单的解决方法就是使用$/ = "\\n"
作为次要说明,你的正则表达式是有缺陷的。您目前正在使用快捷键操作符列出您的翻译s///
。如果任何一个早期的正则表达式与特定行不匹配,则不会尝试其他任何翻译。您应该使用简单的分号来分隔您的正则表达式:
's/\\r/\r/g; s/\\n/\n/g; s/\\t/\t/g; s|\\/|/|g'