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

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

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

다음과 같이 처리하고 싶은 +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

GNU sed의 경우 질문에 따라 -u( ) 옵션을 추가해 볼 수도 있습니다 . --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'

관련 정보