대용량 파일에서 개행 문자가 포함된 문자열 바꾸기

대용량 파일에서 개행 문자가 포함된 문자열 바꾸기

메모리 효율적인 방식으로 문자열을 "바이너리" 검색/대체할 수 있는 비라인 기반 도구를 아는 사람이 있습니까?바라보다이 문제또한.

다음과 비슷한 작업을 수행하려는 +2GB 텍스트 파일이 있습니다.

sed -e 's/>\n/>/g'

이는 a 이후에 발생하는 모든 개행을 제거하고 싶지만 >다른 곳에서 발생하는 개행은 제거하지 않음을 의미합니다 tr -d.

이 명령은 (내가 시작한비슷한 질문에 대한 답변)는 다음과 같이 실패합니다 couldn't re-allocate memory.

sed --unbuffered ':a;N;$!ba;s/>\n/>/g'

그렇다면 C언어 외에 다른 방법은 없을까요? 나는 Perl을 싫어하지만 이 경우에는 예외를 만들고 싶습니다 :-)

데이터에 문자가 있는지 확실하지 않으므로 \n가능하면 다른 문자로 임시 대체하는 것을 피하고 싶습니다.

좋은 아이디어가 있나요?

답변1

이것은 Perl에서는 정말 사소한 일이므로 미워해서는 안 됩니다!

perl -i.bak -pe 's/>\n/>/' file

설명하다

  • -i: 파일을 제자리에서 편집하고 이라는 원본 파일의 백업을 만듭니다 file.bak. 백업이 필요하지 않으면 그냥 사용하세요 perl -i -pe.
  • -pe: 입력 파일을 한 줄씩 읽고 주어진 스크립트를 적용한 후 각 줄을 인쇄합니다 -e.
  • s/>\n/>/: 교체하세요 sed.

awk한 가지 방법 은 다음과 같습니다 .

awk  '{if(/>$/){printf "%s",$0}else{print}}' file2 

답변2

일방 perl통행:

$ perl -pe 's/(?<=>)\n//'

설명하다

  • s///문자열 교체에 사용됩니다.
  • (?<=>)뒤돌아보기 모드입니다.
  • \n개행 문자와 일치합니다.

전체 패턴은 >이전의 모든 줄 바꿈을 제거하는 것을 의미합니다.

답변3

이건 어때:

sed ':loop
  />$/ { N
    s/\n//
    b loop
  }' file

-uGNU sed의 경우 질문에 따라 () 옵션을 추가해 볼 수도 있습니다 . --unbufferedGNU sed는 이것을 간단한 한 줄짜리로 기쁘게 생각합니다:

sed ':loop />$/ { N; s/\n//; b loop }' file

답변4

sed최종 개행 없이 출력을 내보내는 방법을 제공하지 않습니다. 사용 중인 접근 방식은 N기본적으로 유효하지만 불완전한 줄을 메모리에 저장하므로 줄이 너무 길어지면 실패할 수 있습니다(sed 구현은 일반적으로 극도로 긴 줄을 처리하도록 설계되지 않았습니다).

대신 awk를 사용할 수 있습니다.

awk '{if (/<$/) printf "%s", $0; else print}'

또 다른 접근 방식은 자주 발생하는 "지루한" 문자를 사용하여 tr줄 바꿈을 바꾸는 것입니다. 여기서는 공백이 중요한 역할을 할 수 있습니다. 데이터의 모든 줄이나 적어도 대부분의 줄에 나타나는 경향이 있는 문자를 선택하세요.

tr ' \n' '\n ' | sed 's/> />/g' | tr '\n ' ' \n'

관련 정보