Using sed in bash script to replace LaTeX aliases
Asked Answered
T

3

4

I am relatively new to bash scripting and have no experience with LaTeX. I've been asked to develop a script which will replace convenience shortcuts in LaTeX documents with their more cumbersome long-form equivalents.

My approach thus far has been to isolate both the shortcut and the long-form in separate variables and then try to replace them in the text by using sed. I've attached short example files below.

As it is currently the script takes 2 arguments, a file expr from which it retrieves the shortcuts and long-form terminology and an infile to which is is supposed to make the appropriate changes. I know that the script is properly isolating both the shortcuts and long-forms and can return them, but it can't seem to execute the sed command.

I have tried searching this online and found multiple similar question where the suggestion was that sed has difficultly recognizing variable and that various type of quotation combinations might solve the problem. I have tried many permutations and none appear to work. The long-form terminologies in many cases contain special characters such as '$' and '{}', so I suspect that this might be the issue but I'm not sure. I am also very much open to other ideas about how to solve the problem. Please find below samples of both the script and the 2 argument files, expr and infile.

expr file containing shortcuts and long-forms

% a
\newcommand{\ao}{$^{18}$O}
\newcommand{\aodso}{$^{18}$O/$^{16}$O}
% b
\newcommand{\bea}{\begin{equation}}
\newcommand{\beaa}{\begin{eqnarray}}
% c
\newcommand{\cthree}{C$_3$}
\newcommand{\cfour}{C$_4$}
\newcommand{\coz}{CO$_2$}

infile containing shortcuts to be replaced by long-forms

This is my test {\ao} 
{\aodso} my test is this
Does it work {\bea}
{\beaa} test test test
work work work {\cthree}
{\cfour} This is my test
my test is this {\coz}

Relevant subsection of script called with expr and infile as arguments

while read line; do
    if [[ $line == \newcommand* ]]; then
    temp=${line#*\{}
    sc=${temp%%\}*} 
    templf=${temp#*\{}
    lf=${templf%\}}
    #echo $sc, $lf
    sed -i -e 's/${sc}/${lf}/g' ${infile}
    fi
done < ${expr}

UPDATE: For clarification, this is what the desired result would be, the shortcuts present in infile would be substituted with the appropriate long-form

This is my test {$^{18}$O}
{$^{18}$O/$^{16}$O} my test is this
Does it work {\begin{equation}}
{\begin{eqnarray}} test test test
work work work {C$_3$}
{C$_4$} This is my test
my test is this {CO$_2$}
Twitter answered 22/7, 2013 at 17:33 Comment(3)
You provided the two input files. Good. Now add the wanted output. Easier to understand what you need.Liverpudlian
The desired output would be to replace all the shortcuts with the long-forms in the infile so that it would look like this codeThis is my test {$^{18}$O} code{$^{18}$O/$^{16}$O} my test is this codeDoes it work {\begin{equation}} code{\begin{eqnarray}} test test test codework work work {C$_3$} code{C$_4$} This is my test codemy test is this {CO$_2$}Twitter
Possible duplicate of Transform a tex source so that all macros are replaced by their definitionSpinous
V
5

Code for GNU :

sed -r '/^%/d;s#.*\b(\{\\\w+\})(\{.*\})#\1 \2#;s#\\#\\\\#g;s#(\S+)\s(\S+)#\\|\1|s|\1|\2|g#' file1|sed -f - file2

$ cat file1
% a
\newcommand{\ao}{$^{18}$O}
\newcommand{\aodso}{$^{18}$O/$^{16}$O}
% b
\newcommand{\bea}{\begin{equation}}
\newcommand{\beaa}{\begin{eqnarray}}
% c
\newcommand{\cthree}{C$_3$}
\newcommand{\cfour}{C$_4$}
\newcommand{\coz}{CO$_2$}

$ cat file2
This is my test {\ao}
{\aodso} my test is this
Does it work {\bea}
{\beaa} test test test
work work work {\cthree}
{\cfour} This is my test
my test is this {\coz}

$ sed -r "/^%/d;s#.*\b(\{\\\w+\})(\{.*\})#\1 \2#;s#\\#\\\\#g;s#(\S+)\s(\S+)#\\|\1|s|\1|\2|g#" file1|sed -f - file2
This is my test {$^{18}$O}
{$^{18}$O/$^{16}$O} my test is this
Does it work {\begin{equation}}
{\begin{eqnarray}} test test test
work work work {C$_3$}
{C$_4$} This is my test
my test is this {CO$_2$}

Explanation:

There are two calls for sed, the first one makes from the file with the search/replace patterns a sed script:

sed -r '/^%/d;s#.*\b(\{\\\w+\})(\{.*\})#\1 \2#;s#\\#\\\\#g;s#(\S+)\s(\S+)#\\|\1|s|\1|\2|g#' file1
\|{\\ao}|s|{\\ao}|{$^{18}$O}|g
\|{\\aodso}|s|{\\aodso}|{$^{18}$O/$^{16}$O}|g
\|{\\bea}|s|{\\bea}|{\\begin{equation}}|g
\|{\\beaa}|s|{\\beaa}|{\\begin{eqnarray}}|g
\|{\\cthree}|s|{\\cthree}|{C$_3$}|g
\|{\\cfour}|s|{\\cfour}|{C$_4$}|g
\|{\\coz}|s|{\\coz}|{CO$_2$}|g

In the second call sed processes this script with the text file to make the replacements.

sed -f - file2
Vaporing answered 22/7, 2013 at 19:38 Comment(2)
I was wondering if you could maybe explain how the sed command works? I've gone through it but I can't quite figure it out. What do the '#' mean in this context? Is it related to the -r flag? I understand that /^%/d; is saying if the line begins with %, skip it But I can't understand the body, can you offer any clarification?Twitter
@Twitter please see my answer. I use # as replacement for / to enable the build of a sed script with sed itselfes. Please accept my answer if it works for you: Accepting Answers: How does it work?--thanks :)Vaporing
S
1

There's a lot of discussion of this issue on this question at tex.SE. But I'll take the opportunity to note that the best answer there (IMO) is to use the de-macro program, which is a python script that comes with TeXLive. It's quite capable, and can handle arguments as well as simple replacements.

To use it, you move the macros that you want expanded into a <something>-private.sty file, and include it into your document with \usepackage{<something>-private}, then run de-macro <mydocument>. It spits out <mydocument>-private.tex, which is the same as your original, but with your private macros replaced by their more basic things.

Spinous answered 19/4, 2016 at 15:47 Comment(0)
M
0

I know that this question has been marked as answered since quite a while and that you explicitly mention bash and sed as your desired tool.

However, in the interest of others and if you don't insist on bash and sed there exist other options for your problem, e.g. the perl script TME (as suggested here on SO). Usage:

tme  [ -c ]  [ -D | -Dn ]  [ macros.tex ... ]  <input.tex  >output.tex
Miscarry answered 3/6, 2014 at 8:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.