대용량 파일에서 여러 줄 표현식과 함께 sed를 사용할 때 메모리 부족

대용량 파일에서 여러 줄 표현식과 함께 sed를 사용할 때 메모리 부족

현재 닫는 괄호가 앞에 오지 않은 모든 개행 문자를 제거하려고 하므로 다음 표현식을 생각해 냈습니다.

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'

대칭을 위해: 스크립트를 루프로 감싸고 한 줄씩 읽고 인쇄합니다. /script -p표현식은 줄 끝에서 일치하며, 일치하지 않으면(일치가 false) 계속해서 줄 바꿈을 제거합니다. 끝.-e)chomp

답변3

이것을 사용하십시오 :

sed -i -z -u 's/\n/ /g' reallyBigFile.log

-z, --null-data
NUL 문자로 줄을 구분합니다.

-u, --unbuffered는
입력 파일에서 최소한의 데이터를 로드하고 출력 버퍼를 더 자주 플러시합니다.

관련 정보