Sed alternative for search and replace on very long lines
You can use another tool that lets you set the input record separator. For example
Perl
perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
The special variable
$/
is the input record separator. Setting it to}{
defines lines as ending in}{
. That way you can achieve what you want without reading the entire thing into memory.mawk or gawk
awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file
This is the same idea.
RS="}{"
sets the record separator to}{
and then you print}
, a newline,{
(except for the first record) and the current record.
Perl to the rescue:
perl -i~ -e ' $/ = \1024;
while (<>) {
print "\n" if $closing and /^{/;
undef $closing;
s/}{/}\n{/g;
print;
$closing = 1 if /}$/;
} ' input1 input2
Setting $/
to \1024
will read the file in chunks of 1024 bytes. The $closing
variable handles the case when a chunk ends in }
and the next one starts with {
.
You should do:
{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile
It's probably the most efficient solution.
That puts a {}
to protect any possible trailing data. With one more tr
process you can swap that around and do a blank line at the head of the first {
field. Like...
tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}
So the first, with don's example data, does:
printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; } |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}
...and the second one does...
printf '{one}{two}{three}{four}' |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}
There is no trailing newline for the second example - though there is one for the first.