메모리 효율적인 방식으로 문자열을 "바이너리" 검색/대체할 수 있는 비라인 기반 도구를 아는 사람이 있습니까?바라보다이 문제또한.
다음과 비슷한 작업을 수행하려는 +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
-u
GNU sed의 경우 질문에 따라 () 옵션을 추가해 볼 수도 있습니다 . --unbuffered
GNU 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'