[Tex/LaTex] Automatically replace all |foo| with \abs{foo}

editorsmath-modescripts

Technically speaking, this isn't a LaTeX specific question, but there are so many useful tools in LaTeX, and I'm using it to solve a LaTeX problem, so I thought here would be a good place to ask.

I have a rather large document with lots of math notation. I've used |foo| throughout to indicate the absolute value of foo. I'd like to replace every instance of |foo| with \abs{foo}, so that I can control the notation via an abs macro I define.

Does anybody know of a way to do this? Possibly using regular expressions of some sort? Are there editors with tools built in for this?

Best Answer

Option 1: sed

The stream editing tool, sed, would be a natural first choice, but the problem is that sed can't match non-greedy regular expressions.

We need a non-greedy regular expression here- to clarify why, let's consider

sed -r 's/|(.*)|/\\abs{\1}/g' myfile.tex

If we apply this substitution to a file that contains something like

$|a|+|b|\geq|a+b|$

then we'll get

$\abs{a|+|b|\geq|a+b}$

which is clearly not what we want- regular expression matches like this are greedy by default.

To make it non-greedy, we typically use .*?, but the problem is that sed does not support this type of match. Happily (thanks Hendrik) we can use the following instead

sed -r 's/\|([^|]*)\|/\\abs{\1}/g' myfile.tex

Once you're comfortable that it does what you want, you can use

sed -ri.bak 's/\|([^|]*)\|/\\abs{\1}/g' myfile.tex

which will overwrite each file, and make a back up first, myfile.tex.bak

Option 2: perl

We could, instead, use a little perl one-liner:

perl -pe 's/\|(.*?)\|/\\abs{\1}/g' myfile.tex

When you're sure that you trust it is working correctly, you can use the following to overwrite myfile.tex

perl -pi -e 's/\|(.*?)\|/\\abs{\1}/g' myfile.tex

You can replace myfile.tex with, for example, *.tex to operate on all the .tex files in the current working directory.

Details of perl's switches are discussed here (for example): http://perldoc.perl.org/perlrun.html#Command-Switches