1

I am using perl to parse many multilingual text files. I need to change the text between two patterns:

Desired Changes

For example, the English original version looks like this:

\label{whatever}
\ref{whatever}
\autoref{whatever}

but the stuff between {and } should be suffixed with the appropriate ISO 639 language code e.g.

\label{whatever_de}
\ref{whatever_de}
\autoref{whatever_de}

Assumptions for Testing

Given the following files:

da/myfile_da.tex
de/myfile_de.tex
el/myfile_el.tex
en/myfile_en.tex

and each file contains:

\label{some_nice_thing}
\ref{some_nice_thing}
\autoref{some_nice_thing}

My Approach

I can use folder names as my ISO 639 codes and create a simple loop through the files. The following should simply print the changed lines to the terminal console. I will try to explain the peculiar results I am getting by example:

Working: \\label\{.*?\}

for f in *; do  if [[ -d $f ]]; then perl -ne "print if s/(\\label\{.*?)\}/\1_$f\}/g"  $f/myfile_$f.tex; fi; done

Not Working: \\ref\{.*?\}

for f in *; do  if [[ -d $f ]]; then perl -ne "print if s/(\\ref\{.*?)\}/\1_$f\}/g"  $f/myfile_$f.tex; fi; done

Not Working: \\autoref\{.*?\}

for f in *; do  if [[ -d $f ]]; then perl -ne "print if s/(\\autoref\{.*?)\}/\1_$f\}/g"  $f/myfile_$f.tex; fi; done

Note that grep -Pr works with each case (removing groups, of course)

2 Answers 2

4

\\ becomes \ in double quotes. \\ref becomes \ref which is in fact \r followed by ef. Use four backslashes:

for f in *; do
    if [[ -d $f ]]; then
        perl -ne "print if s/(\\\\ref\{.*?)\}/\1_$f\}/g" $f/SystemRequirements_$f.tex
    fi
done

Similarly, \a is the BELL character (\x07).

3
  • Thanks! Your answer is great for the extra info. I accepted muru's answer because it also answers correctly and accurately and was first. But I am sure the alternative \\\\ and \x07 will come in handy for some future readers. Feb 17, 2016 at 21:28
  • Do you know why in-place editing does not work here e.g. perl -ei? Obviously, this is above and beyond the original question. Feb 17, 2016 at 21:38
  • 2
    @macmadness86: -ei is wrong, code must follow e.
    – choroba
    Feb 17, 2016 at 21:40
2

It's a quoting problem. You're using double quotes for the $f variable, but double quotes also have other implications. In particular, they allow backslash-escaping of characters, so \\ becomes \ when it reaches Perl:

$ printf "%s\n" "print if s/(\\label\{.*?)\}/\1_$f\}/g"
print if s/(\label\{.*?)\}/\1_\}/g

This creates a problem with r, because \r will be seen as the return character (see perlrebackslash) - it won't match r. Use single quotes instead, only opening for the variable:

$ printf "%s\n" 'print if s/(\\label\{.*?)\}/\1_'"$f"'\}/g'
print if s/(\\label\{.*?)\}/\1_\}/g

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .