6

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!

1
  • 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 [^}]*. – berndbausch Feb 2 at 13:44
5

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.

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

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.

3
  • Ah, you were faster again! :) – AdminBee Feb 2 at 10:25
  • 1
    @AdminBee yes, but you were cleverer. Simplifying the replacement is a nice touch! – terdon Feb 2 at 10:26
  • Yes, that was the key step I was missing (looking for non-} characters instead). Thanks for the quick response. – Steve H Feb 2 at 13:29
3

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}$
1
  • 1
    @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. – schrodigerscatcuriosity Feb 2 at 11:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.