4

I am trying to use perl in order to modify a LaTeX document. In fact, I am trying to change the citation format from for example:

. \cite{poelma20113d}

to

\cite{poelma20113d}.

In other words, I want to find those citations which are preceded by a period and a space and replace them with blank then put the citation and then place a period after it. Could someone help me how I can do that via perl one liner? The reason I want to do this is that I want to change the format of my manuscript that was prepared for the Journal of Physics of Fluids to the Journal of Physical Review E.

  • How robust does it need to be? Do you ever have an optional argument \cite[]{} or an alternative macro \citet{}? – StrongBad May 31 '14 at 14:27
  • Actually I am changing the format of my manuscript from Physics of Fluids to Physical Review E. – AFP May 31 '14 at 19:26
1

This will find and perform the swap as you're inquiring about:

$ perl -lpe 's/\. (\\cite.*)/$1./' afile 
\cite{poelma20113d}.

To have the one liner make the actual change to the file:

$ perl -i.bak -lpe 's/\. (\\cite.*)/$1./' afile 

This will keep the original file in afile.bak. If you want to forgo having the .bak files created you can tell perl to not do this by omitting any argument to the -i switch:

$ perl -i -lpe 's/\. (\\cite.*)/$1./' afile 

How it works

The above examples look for the following bits within each string of file afile.

  • \. - looks for a literal ..
  • s/.../../ - searches for a pattern and replaces it with another pattern.
  • (\\cite.*) - looks for the pattern of a literal \ followed by the string cite, followed by anything else. All this is saves in a variable, $1 because it's wrapped in parens (i.e. (....)). Note: (\\cite.*}) will stop when it reaches the right curly brace }. This way, the next sentence after the LaTeX \cite{} command for example in . \cite{poelma20113d} This is the next sentence. will be processed correctly.
  • $1. - $1 is what we matched in the parens, so we put that out followed by a ..
  • Thank you. Very efficient way. Can I know what \. (\\cite.*) does? I understand the first part: \. which finds the period and space. I wanted to know what (\\cite.*) does. – AFP May 31 '14 at 19:29
  • @A2009 - let me know if that clears it up. – slm May 31 '14 at 20:54
  • Wonderful explanation and nice formatting in "How it works". Loved it! – AFP May 31 '14 at 21:19
  • @A2009 - thanks for the Q, glad to of been of help! – slm May 31 '14 at 21:20
  • 1
    @A2009 - no the .* is greedy, it will stop at the end of a line. A curly brace could be put there to stop it though, (\\cite.*}). – slm May 31 '14 at 21:41
2

I am pretty sure LaTeX can only be properly parsed with LaTeX1 and implementing LaTeX in Perl would be a real challenge. Therefore any trivial Perl solution will fail on some edge conditions. Working off of the following example

This is cite{foo}. \cite{foo} This is cite[foo]{bar}. \cite[foo]{bar} This is citet{foo, bar}.\citet{foo, bar}

which covers a single optional argument, multiple citations, alternative forms of \cite that start with \cite, and variable amount of white space between the . and the \cite. The following perl expression seems to do what you need

perl -pe 's/(.\s*)(\\cite)([^{]*)(\[[^\]]*\])?{([^}]*)}/\2\3\4\{\5\}./g' afile

This is cite{foo}\cite{foo}. This is cite[foo]{bar}\cite[foo]{bar}. This is citet{foo, bar}\citet{foo, bar}.

  • The reason I want to do this is that I want to change the format of my manuscript that was prepared for the Journal of Physics of Fluids to the Journal of Physical Review E. – AFP May 31 '14 at 19:25
  • I would be thankful if you could elaborate on the regular expression: 's/(.\s*)(\\cite)([^{]*)(\[[^\]]*\])?{([^}]*)}/\2\3\4\{\5\}./g' – AFP May 31 '14 at 19:32

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.