10

Thanks to Bruno for suggesting that for my specific case, where my results come from Mathematica, it's simply much easier to change the output in there using trivial replacement rules. However, this stands alone as a general question.

This is a slightly different question to what I've seen before, where I can use something like \newcommand{\ga}{\gamma} to make shortcuts of things using \.

I have a series of LONG equations with stuff like x[2] or a[3] in them. I want to be able to always replace any instance of them with something else, like a command that takes a string and replaces it like something similar to

\newcommand{x[2]}{x_2}

and

\newcommand{a[2]}{\beta}

Ideally, this would take account of the number inside, but I could easily just do it for all instances that arise. Any guidance would be great (my document class is Report)

  • Sort of sounds like translating math equations from one syntax to another, which reminded me of my very strange answer here: tex.stackexchange.com/questions/332012/…. Not that it will help you in the present case, without significant rework. – Steven B. Segletes Mar 26 at 15:46
  • 2
    Do you absolutely need to convert as you typeset, or can you convert your source? If the latter, do you think it would be possible to unambiguously define all the situations in which this syntax would occur? – Chris H Mar 26 at 15:48
  • @ChrisH that's exactly what I'm hoping for. I'm copying some parts of equations from Mathematica, and is written in terms of coefficients like x[2] for example, where I avoided subscripts in my code. I now want to save myself effort and simply define x[2] = x_2 in Latex, since it'll only ever occur within an equation. – Brad Mar 26 at 15:50
  • 3
    My editor of choice supports regex find/replace so I'd simply find x\[([0-9])\] and replace with x_$1 (on a copy of course) – Chris H Mar 26 at 15:54
  • 1
    @CarlWitthoft thank you for your comment. There are plenty of options for going about solving this, but just to keep everything localised within TeX I was looking for a somewhat simple method of achieving this, for applications even beyond this current issue. Alas, it has been solved now, and also in a multitude of methods. One could argue all night about which way is both, however, I certainly see no issue in solving it externally (which I happen to be doing now in Mathematica). – Brad Mar 27 at 13:16
10

An extensible set of replacements:

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\trans}{m}
 {
  \tl_set:Nn \l__brad_trans_tl { #1 }
  \regex_replace_all:nnN { \[(.*?)\] } { \c{sb}\cB\{\1\cE\} } \l__brad_trans_tl
  \regex_replace_all:nnN { a } { \c{alpha} } \l__brad_trans_tl
  % other replacements
  % ...
  % deliver the new token list
  \l__brad_trans_tl
 }
\ExplSyntaxOff

\begin{document}

$\trans{x[1]+x[2]^2+a+a[3]}$

\end{document}

enter image description here

  • 1
    Same comment as I made on David's answer. Yes, my l3regex is sometimes useful, but here the right solution by far is to do the replacements in Mathematica, not TeX. – Bruno Le Floch Mar 26 at 19:34
9

Inasmuch as I love doing crazy things in TeX, do the replacements in Mathematica! This will save you a huge amount of pain. For instance,

expr = (a[1] + a[2])/Sqrt[a[3]]
expr /. {a[1] -> \[Alpha], a[2] -> \[Beta], a[3] -> \[Gamma]} // TeXForm

gives \frac{\alpha +\beta }{\sqrt{\gamma }} with no need to tweak the output.

  • This is actually much more efficient than I realised! I was specifically trying to avid all those dirty symbols in my code but that's a much better overall solution. Big +1, thank you for the advice! I have edited my question to reflect this. I assume one would need to replace x[2] with the full subscript notation to achieve the $x_2$ necessary as well? – Brad Mar 27 at 11:36
  • Yeah, it's just as easy to do the subscript replacements as well. Thank you for pointing this out Bruno; I will keep the answer above since I guess it does answer the specific question in particular, but I appreciate your solution greatly. – Brad Mar 27 at 11:45
7

I really can not recommend doing this, but as you ask...

enter image description here

\documentclass{article}

\begin{document}


\mathcode`\[="8000
\mathcode`\]="8000
{
\catcode`\[=\active \gdef[{_\bgroup}
\catcode`\]=\active \gdef]{\egroup}
}

hmmm
\[
a[1]+a[2]+b[c+d[3]] + x
\]

\end{document}
  • Thank you for your answer - this is not quite what I'm after. But since this is not quite a conventional method, perhaps I am better simply going through and replacing things manually... I am moreso hoping to simply find a particular string and replace it with something else. – Brad Mar 26 at 16:02
  • @Brad that really isn't how tex works:-) (unless you are using luatex) – David Carlisle Mar 26 at 16:05
  • No worries at all! I have no problem sorting through everything, but I was hoping to save myself a bit of eyesight. Thank you for your help regardless! – Brad Mar 26 at 16:06
  • @DavidCarlisle Come on, don't advocate crazy solutions to problems that can be trivially solved on the other side of the conversion. Brad should simply do the replacement in Mathematica. – Bruno Le Floch Mar 26 at 19:33
  • 3
    @BrunoLeFloch I'd already said that in comments under the question, or just use perl or any other sane mechanism, but it's easy for you to see that this is beyond what's reasonable to do in tex as you know more than most on where tex's limits are, but I think it is still useful as a general rule to sketch how far you can get (and in particular what you can not reasonably do) in tex for this kind of question. – David Carlisle Mar 26 at 19:39
5

Along the vein of my cited Translate in-line equations to TeX code (Any Package?), but a much simpler parsing request, I provide \translate.

No catcode changes required. It will retain surrounding math style, etc.

\documentclass{article}
\usepackage{listofitems}
\newtoks\eqtoks
\newcommand\addtoeqtoks[1]{\expandafter\eqtoks\expandafter{\the\eqtoks#1}}
\newcommand\translate[1]{%
  \setsepchar{[||]}%
  \readlist\myeqn{#1}%
  \eqtoks{}%
  \foreachitem\x\in\myeqn[]{%
    \ifnum\xcnt=1\else%
      \if[\myeqnsep[\numexpr\xcnt-1]\addtoeqtoks{_\bgroup}\fi%
      \if]\myeqnsep[\numexpr\xcnt-1]\addtoeqtoks{\egroup}\fi%
    \fi%
    \expandafter\addtoeqtoks\expandafter{\x}%
  }%
  \the\eqtoks%
}
\begin{document}
\[
\translate{a[1]+a[2]+b[c+d[3]] + x}
\]
\end{document}

enter image description here

4

For the sake of variety, here's a LuaLaTeX-based solution. It sets up a Lua function, called trans, which does most of the work with the help of Lua's versatile string-handling routines. The LaTeX macro \trans is a wrapper that invokes the Lua function.

enter image description here

\documentclass{article}
\usepackage{luacode} % for "luacode" environment and "\luastringN" macro
\begin{luacode}
function makesubscr ( s )
  s = s:gsub ( "(%b[])", function(x)
         return ( "_{" .. string.sub ( x , 2 , -2 ) .. "}" )
      end )
  if s:find ( "%b[]" ) then 
      s = makesubscr ( s ) 
  end
  return s
end
function trans ( s )
  s = makesubscr ( s )
  s = s:gsub ( "a" , "\\alpha" )
  s = s:gsub ( "b" , "\\beta" )
  tex.sprint ( s )
end
\end{luacode}

%% TeX-side code
\newcommand\trans[1]{\directlua{trans(\luastringN{#1})}}

\begin{document}
$\trans{x[1]+x[2]^2+a+a[3]}$

$\trans{a[1]+a[2]+b[c+d[3]]+x}$
\end{document}
2

Here's a solution. The command \addreplacementrule{text-to-replace}{replacement-text} specifies replacements to make. Then the command \replace{some math} does the replacements.

This would probably be better done with the l3regex package or really find and replace as many other people mentioned.

\documentclass{article}
\makeatletter
\newtoks\ri@activechars
\def\addreplacementrule#1#2{\addreplacementrule@#1\@nil{#2}}
\def\addreplacementrule@#1#2\@nil#3{%
    \ri@activechars\expandafter{\the\ri@activechars\\#1}%
    \ri@maketransitions#2\@nil{#1}{#3}%
}

\def\replace#1{%
    \begingroup
    \def\\##1{%
        \bgroup\lccode`~=`##1\lowercase{\egroup
            \def~{\ri@continue{##1}}%
        }%
        \catcode`##1=\active
    }%
    \the\ri@activechars
    \scantokens{#1}%
    \endgroup
}

\def\ri@maketransitions#1#2\@nil#3#4{%
    \def\temp{#2}%
    \ifx\temp\empty
        \expandafter\def\csname ri@lookup@\detokenize{#3#1}\endcsname{#4}%
        \let\next\relax
    \else
        \expandafter\def\csname ri@lookup@\detokenize{#3#1}\endcsname{\ri@continue{#3#1}}%
        \def\next{\ri@maketransitions#2\@nil{#3#1}{#4}}%
    \fi
    \next
}


\def\ri@continue#1#2{%
    \@ifundefined{ri@lookup@\detokenize{#1#2}}{%
        \detokenize{#1}#2%  
    }{%
        \csname ri@lookup@\detokenize{#1#2}\endcsname
    }%
}


\begin{document}
\addreplacementrule{x[2]}{x_2}
\addreplacementrule{x[3]}{x^2}

$x+1+x[2]+x[3]+x[1]$

\replace{$x+1+x[2]+x[3]+x[1]$}
\end{document}

enter image description here

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.