
Ich verwende Perl, um viele mehrsprachige Textdateien zu analysieren. Ich muss den Text zwischen zwei Mustern ändern:
Gewünschte Änderungen
Die englische Originalversion sieht beispielsweise so aus:
\label{whatever}
\ref{whatever}
\autoref{whatever}
aber das Zeug zwischen {
und }
sollte mit dem entsprechenden ISO 639-Sprachcode versehen werden, z. B.
\label{whatever_de}
\ref{whatever_de}
\autoref{whatever_de}
Annahmen für Tests
Gegeben seien die folgenden Dateien:
da/myfile_da.tex
de/myfile_de.tex
el/myfile_el.tex
en/myfile_en.tex
und jede Datei enthält:
\label{some_nice_thing}
\ref{some_nice_thing}
\autoref{some_nice_thing}
Mein Ansatz
Ich kann Ordnernamen als ISO 639-Codes verwenden und eine einfache Schleife durch die Dateien erstellen. Das Folgende sollte einfach die geänderten Zeilen auf der Terminalkonsole ausgeben. Ich werde versuchen, die eigenartigen Ergebnisse, die ich erhalte, anhand eines Beispiels zu erklären:
Arbeiten:\\label\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\label\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Funktioniert nicht:\\ref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\ref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Funktioniert nicht:\\autoref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\autoref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Beachten Sie, dass dies grep -Pr
in jedem Fall funktioniert (natürlich auch durch Entfernen von Gruppen).
Antwort1
\\
wird \
in Anführungszeichen. \\ref
wird, \ref
worauf tatsächlich \r
folgt ef
. Verwenden Sie vier Backslashs:
for f in *; do
if [[ -d $f ]]; then
perl -ne "print if s/(\\\\ref\{.*?)\}/\1_$f\}/g" $f/SystemRequirements_$f.tex
fi
done
Ähnlich \a
verhält es sich mit dem Glockenzeichen ( \x07
).
Antwort2
Es ist ein Anführungszeichenproblem. Sie verwenden doppelte Anführungszeichen für die $f
Variable, aber doppelte Anführungszeichen haben auch andere Auswirkungen. Insbesondere ermöglichen sie das Escapen von Zeichen durch Backslashs, sodass es bei Perl zu folgendem Ergebnis \\
kommt :\
$ printf "%s\n" "print if s/(\\label\{.*?)\}/\1_$f\}/g"
print if s/(\label\{.*?)\}/\1_\}/g
Dies führt zu einem Problem mit r
, da \r
als Return-Zeichen angesehen wird (sieheperlrebackslash
) - es wird nicht übereinstimmen r
. Verwenden Sie stattdessen einfache Anführungszeichen, die nur für die Variable öffnen:
$ printf "%s\n" 'print if s/(\\label\{.*?)\}/\1_'"$f"'\}/g'
print if s/(\\label\{.*?)\}/\1_\}/g