我目前正在尝试删除所有前面没有右括号的换行符,所以我想出了这个表达式:
sed -r -i -e ":a;N;$!ba;s/([^\)])\n/\1/g;d" reallyBigFile.log
它可以在较小的文件上完成工作,但在我使用的这个大文件上(3GB
),它可以工作一段时间,然后返回并出现内存不足错误:
sed: Couldn't re-allocate memory
有什么办法可以在不遇到这个问题的情况下完成这项工作。使用sed
本身并不是强制性的,我只是想完成它。
答案1
你的前三个命令是罪魁祸首:
:a
N
$!ba
这会立即将整个文件读入内存。以下脚本一次只能在内存中保留一个段:
% cat test.sed
#!/usr/bin/sed -nf
# Append this line to the hold space.
# To avoid an extra newline at the start, replace instead of append.
1h
1!H
# If we find a paren at the end...
/)$/{
# Bring the hold space into the pattern space
g
# Remove the newlines
s/\n//g
# Print what we have
p
# Delete the hold space
s/.*//
h
}
% cat test.in
a
b
c()
d()
e
fghi
j()
% ./test.sed test.in
abc()
d()
efghij()
这个 awk 解决方案将打印每一行,因此内存中一次只有一行:
% awk '/)$/{print;nl=1;next}{printf "%s",$0;nl=0}END{if(!nl)print ""}' test.in
abc()
d()
efghij()
答案2
为了完整起见,Perl 解决方案:perl -p -e '/)$/ || chomp'
为了对称:-p
将脚本包装在循环中,逐行读取和打印;表达式-e
/脚本)
在行尾匹配,如果不匹配(匹配为假),则继续到chomp
,这会删除末尾的换行符。
答案3
用这个:
sed -i -z -u 's/\n/ /g' reallyBigFile.log
-z, --null-data
用 NUL 字符分隔行
-u, --unbuffered
从输入文件加载最少量的数据并更频繁地刷新输出缓冲区