레코드 끝에 줄 바꿈을 추가하지 않는 프로그램에 의해 생성된 일부 파일이 있습니다. 레코드 사이에 줄바꿈을 추가하고 싶습니다. 간단한 sed 스크립트를 사용하여 이 작업을 수행할 수 있습니다.
sed -e 's/}{/}\n{/g'
문제는 입력 파일의 크기가 여러 GB이므로 sed에 대한 입력 줄의 길이가 여러 GB라는 것입니다. sed는 메모리에 한 줄을 저장하려고 시도하지만 이 경우에는 작동하지 않습니다. 해당 옵션을 시도했지만 --unbuffered
속도가 느려지고 올바르게 완료되지 않는 것 같습니다.
답변1
다른 도구를 사용하여 입력 레코드 구분 기호를 설정할 수 있습니다. 예를 들어
펄
perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
특수 변수
$/
는 입력 레코드 구분 기호입니다.}{
로 끝나는 줄을 정의하도록 설정합니다}{
. 이렇게 하면 전체 내용을 메모리로 읽지 않고도 원하는 것을 얻을 수 있습니다.모하거나 꾸물거리다
awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file
같은 생각이에요.
RS="}{"
레코드 구분 기호를 로 설정한}{
다음 ,}
개행{
(첫 번째 레코드 제외) 및 현재 레코드를 인쇄합니다.
답변2
Perl이 구조에 옵니다:
perl -i~ -e ' $/ = \1024;
while (<>) {
print "\n" if $closing and /^{/;
undef $closing;
s/}{/}\n{/g;
print;
$closing = 1 if /}$/;
} ' input1 input2
1024바이트 단위로 파일을 읽도록 $/
설정 합니다 . \1024
이 변수는 한 블록이 로 끝나고 다음 블록이 로 시작하는 $closing
경우를 처리합니다 .}
{
답변3
당신이 해야 할 일:
{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile
이것이 아마도 가장 효율적인 솔루션일 것입니다.
이는 {}
가능한 모든 추적 데이터를 보호합니다. 다른 tr
프로세스를 사용하면 이를 교체하고 첫 번째 필드의 머리 부분에 빈 줄을 추가할 수 있습니다 {
. 좋다...
tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}
따라서 첫 번째는 don의 예제 데이터를 사용하여 다음과 같습니다.
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}
두 번째 예에는 후행 줄 바꿈이 없습니다. 첫 번째 예에는 하나가 있지만.
답변4
다음과 같은 바이너리 sed
유사 유틸리티입니다.bbe
이 경우에는 sed와 유사한 구문을 사용하는 것이 가장 쉽다고 생각합니다.
나많은이 bbe
유틸리티를 사용하는 것이 좋습니다({uni,linu}x 패키지 설치 eq를 통해 사용 가능 apt-get
). 또는여기당신이 git 군중의 일부라면 나는 개인적으로 특정 링크를 검토하지 않았습니다.
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}
(물론 후행 캐리지 리턴이 없습니다.)