어느 정도 메모리 효율적인 방식으로 문자열을 "바이너리" 검색/대체하는 비라인 기반 도구를 아는 사람이 있습니까?보다이 질문도.
다음과 같이 처리하고 싶은 +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
( ) 옵션을 추가해 볼 수도 있습니다 . --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'