# Replace to first matching character using sed

Trying to update some latex code. The four lines:

something $^\text{TT}$ and more stuff
something $^\text{T}$ and more stuff
something $^\text{M\times N}$ and more stuff
something $^\text{T} {otherstuff}$


should turn into

something $^{\text{TT}}$ and more stuff
something $^{\text{T}}$ and more stuff
something $^{\text{M\times N}}$ and more stuff
something $^{\text{T}} {otherstuff}$


In other words, encase the super-script by an extra {...}.

My attempt at using sed is the following

sed 's/\^\\text{$$.*$$}/\^{\\{text{\1}}/' testregex


This works on the first three lines, but the final line doesn't work and produces

something $^{\text{T} {otherstuff}}$


instead. The problem is that sed is matching with the last } on each line, but I need it to match the first } after the \text{

Also, it would be great if this could work multiple times on the same line, for example,

^\text{1} la la la ^\text{2}


should turn into

^{\text{1}} la la la ^{\text{2}}


I'm sure there's just one tiny little modification to make it work, but I can't figure it out and it's driving me nuts. Thanks in advance!

• Describe what exactly you want to wrap in {...}. I understand that ^\text{SOMETHING} needs to be converted to ^{\text{SOMETHING}}. Is that correct? Can SOMETHING contain curly braces, i.e. nested braces? If not, it should be feasible. The regular expression to be converted would be something like \^\\text{[^}]*} (which would include an empty SOMETHING), i.e. replace the .* in your expression with a more limited [^}]*. Feb 2, 2021 at 13:44

One method to overcome the greedy regular expression problem is to explicitly look for a string of non-delimiter characters, followed by the delimiter character. At the same time, you can probably simplify your replacement syntax via:

sed 's/\^$$\\text{[^}]*}$$/\^{\1}/' input.tex


It should be possible to use

sed 's/\^$$\\text{[^}]*}$$/\^{\1}/g' input.tex


for multiple matches per line.

• Awesome, thanks! This is exactly what I was looking for. Feb 2, 2021 at 13:22
• @SteveH you're welcome! Feb 2, 2021 at 14:07

You're almost there! Instead of looking for "0 or more characters" inside the \text{} block as you do with \\text{$$.*$$}, look for "0 or more non-} characters":

$sed 's/\^\\text{$$[^}]*$$}/\^{\\{text{\1}}/g' foo.tex something$^{\{text{TT}}$and more stuff something$^{\{text{T}}$and more stuff something$^{\{text{M\times N}}$and more stuff something$^{\{text{T}} {otherstuff}$ The g I added to the end turns on global matching which means that all matches on the line will be replaced. Note that this assumes that matches are non-overlapping, it won't work for something like this: something$^{\{text{$^{\{text{BB}}$}}$and more stuff  I am assuming that isn't a problem here though. • Ah, you were faster again! :) Feb 2, 2021 at 10:25 • @AdminBee yes, but you were cleverer. Simplifying the replacement is a nice touch! – terdon Feb 2, 2021 at 10:26 • Yes, that was the key step I was missing (looking for non-} characters instead). Thanks for the quick response. Feb 2, 2021 at 13:29 I propose this: $ sed 's/\$\^\\$$[^}]*$$/$^\{\\\1}/' file
something $^{\text{TT}}$ and more stuff
something $^{\text{T}}$ and more stuff
something $^{\text{M\times N}}$ and more stuff
something $^{\text{T}} {otherstuff}$

• @AdminBee Quasímodo My first attempt was the now edited one, I was trying to simplify the pattern too much it seems, thank you both. I hope there're no problems with this my original one. Feb 2, 2021 at 11:58