I am converting a custom markup language to TeX.
I have a file like this:
\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}
these are extra lines
another extra line
there can be any number of extra lines
e
\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}
this is extra
this is extra too
e
I need the result to be this:
\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}{
these are extra lines
another extra line
there can be any number of extra lines
}
\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}{
this is extra
this is extra too
}
Notice e
is by itself on a line, indicating the end of a set of data, it simply gets replaced with a closing bracket.
I could simply use this:
sed -i 's/^e$/}/g' file.tex
Resulting in this:
\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}
these are extra lines
another extra line
there can be any number of extra lines
}
\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}
this is extra
this is extra too
}
The problem is, I also need a matching starting bracket to surround this extra text before the e
.
One way to think of it is:
}
.e
appearing completely by itself.This is the closest I can figure, not sure how to match across any number of lines not containing more matches of }$
:
sed -i 's/}$\n.*\n.*\n.*\n^e$/}{&}/g' file.tex
How can I wrap that final extra text inside {
and }
?
It is easier to do this using awk
using an empty RS
. Here is a gnu-awk
solution:
awk -v RS= '{sub(/.*}/, "&{"); sub(/\ne$/, "\n}"); ORS=RT} 1' file
\macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}{
these are extra lines
another extra line
there can be any number of extra lines
}
\macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}{
this is extra
this is extra too
}
Or in any version of awk
:
awk -v RS= '{sub(/.*}/, "&{"); sub(/\ne$/, "\n}\n")} 1' file
Not as short or elegant as @anubhava's awk
solution, but as an exercise I implemented the same in GNU sed
.
sed -n '/^e$/{ z; x; s/.*}/&{/; s/$/\n}/; p; d; }; /^$/d; H; ${ H; x; p; }' file
Breaking it out -/^e$/{ z; x; s/.*}/&{/; s/$/\n}/; p; d; };
by component.../^e$/{ ... }
performs this list of actions on a line with just e
:z
is a GNU option that empties the pattern space.x
ex
changes the pattern and hold spaces.s/.*}/&{/
adds an open paren after the last close paren in the block.s/$/\n}/
adds a newline and }
where the e
was.p
will p
rint the pattern space, and d
will d
elete the record and move on.
/^$/d
removes the empty records between.H
says H
old (append) the pattern space record onto the hold space, so that we accumulate the block until we hit the next e
terminator line, or the end.
${ H; x; p; }
just makes sure to print any record(s) after the last e
.
Skip that if you don't care, or if you know there shouldn't be any.
If you aren't using GNU sed
, it would look a bit different, lol
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With