매우 긴 줄에서 검색 및 교체를위한 sed 대안


9

레코드 끝에 줄 바꿈을하지 않은 프로그램으로 생성 된 파일이 있습니다. 레코드 사이에 줄 바꿈을 넣고 싶습니다. 간단한 sed 스크립트로 할 수 있습니다.

sed -e 's/}{/}\n{/g'

문제는 입력 파일의 크기가 수 기가 바이트이므로 sed의 입력 행 길이가 여러 GB라는 것입니다. sed는 메모리에 줄을 유지하려고 시도하지만이 경우 작동하지 않습니다. --unbuffered옵션을 사용해 보았지만 속도가 느려지고 올바르게 완료되지 않았습니다.


아이디어를 시도 할 수있는 예제 입력 파일을 업로드 할 수 있습니까?
mkc 2015 년

3
어쩌면 먼저 사용할 수있는 tr번역 }으로 \n사용 다음과 sed을 추가 할 }각 줄의 끝에서? 이처럼 :tr '}' '\n' < your_file.txt| sed 's/$/}/'
user43791

파일 끝에 줄 바꿈을 추가해도 도움이됩니까? 마찬가지로 :printf "\n" >> file
보모

1
@ Ketan, 78GB 가비지 문자가있는 파일을 }{몇 기가 바이트가 충분할 때까지 반복하여 작성한다고 가정 합니다.
nanny

@ nanny-좋은 지적-그러나 당신은 78을 어디서 얻습니까? 레코드가 이미 차단 된 경우에는 dd if=file cbs=80 conv=unblock그렇게되지만 그렇게 간단하지는 않습니다.
mikeserv

답변:


7

입력 레코드 구분 기호를 설정할 수있는 다른 도구를 사용할 수 있습니다. 예를 들어

  • perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
    

    특수 변수 $/는 입력 레코드 구분 기호입니다. }{로 끝나는 라인 을 정의 하도록 설정합니다 }{. 그렇게하면 전체 내용을 메모리로 읽지 않고도 원하는 것을 얻을 수 있습니다.

  • mawk 또는 gawk

    awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file 
    

    이것은 같은 생각입니다. RS="}{"레코드 구분 기호를로 설정 한 }{다음 }줄 바꿈 {(첫 번째 레코드 제외) 및 현재 레코드를 인쇄합니다.


3

구조에 펄 :

perl -i~ -e ' $/ = \1024;
              while (<>) {
                  print "\n" if $closing and /^{/;
                  undef $closing;
                  s/}{/}\n{/g;
                  print;
                  $closing = 1 if /}$/;
              } ' input1 input2

설정 $/하려면 \10241024 바이트의 덩어리에서 파일을 읽습니다. $closing변수를 취급하는 경우에 때 청크 단부 }와 함께 개시 한 다음 {.


1
+1, 아마도 가장 좋은 해결책; 다른 perl / awk 솔루션도 잘 작동하지만 약 17GB의 문자 후에 첫 번째 레코드 구분 기호가 발생하면 어떻게됩니까?
don_crissti

2

해야 할 일 :

{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile

아마도 가장 효율적인 솔루션 일 것입니다.

따라서 {}가능한 모든 후행 데이터를 보호 할 수 있습니다. 하나 이상의 tr프로세스를 사용하면 그 주위를 바꾸고 첫 번째 {필드 의 머리 부분에 빈 줄을 쓸 수 있습니다 . 처럼...

tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}

따라서 예제 데이터가있는 첫 번째는 다음과 같습니다.

printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; }           |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}

... 두 번째는 ...

printf '{one}{two}{three}{four}'      |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}

두 번째 예에는 후행 줄 바꿈이 없지만 첫 번째 예에는 줄 바꿈이 없습니다.


0

이진 sed같은 유틸리티라는bbe

이 경우 sed와 같은 구문을 유지하는 것이 가장 쉽다는 것을 알았습니다.

유틸리티를 사용하는 것이 훨씬bbe 좋습니다 ({uni, linu} x의 패키지 설치 eq를 통해 사용 가능 apt-get). 또는 여기 당신이 자식 군중 중 하나라면, 나는 개인적으로 그 특정 링크를 조사하지 않았습니다.

1. s/before/after/관용구를 지원합니다

"바이너리 블록 편집기"로, sed와 같은 (다른 것들과 같은) 작업을 지원합니다. 여기에는 필요한 초 공용 s/before/after/대체 관용구가 포함됩니다 . 자체 bbe관점 에서 선이 없기 때문에 명령 끝에 "전역 g"가 없습니다.

빠른 테스트로 (필수 사항 참조 -e) :

$ echo hello | bbe -e 's/l/(replaced)/'

생산 :

he(replaced)(replaced)o

의 특정의 경우 2 }{}\n{변환

우리가 (말) 형식 만 개 숫자로 가득 찬 거대한 파일했다 그렇다면 {1}{2}{3}... {1000000}왕복 수익률을, 우리는 교환 수 }{}\n{쉽게, 그리고 모든 숫자를 한 줄에 하나씩 있습니다.

이것은 다음 bbe명령으로 이루어집니다 :

bbe -e 's/}{/}\n{/'

이 zsh 루프에서 테스트 한대로 다음을 수행합니다.

$ for ((num=0; num<1000000; num++)) do; echo -n "{$num}"; done | bbe -e 's/}{/}\n{/' | tail

어느 것이 이것을 생산할 것인가?

{999990}
{999991}
{999992}
{999993}
{999994}
{999995}
{999996}
{999997}
{999998}
{999999}

(물론 후행 캐리지 리턴없이)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.