
Estoy usando Perl para analizar muchos archivos de texto multilingües. Necesito cambiar el texto entre dos patrones:
Cambios deseados
Por ejemplo, la versión original en inglés se ve así:
\label{whatever}
\ref{whatever}
\autoref{whatever}
pero las cosas entre {
y }
deben tener el sufijo del código de idioma ISO 639 apropiado, por ejemplo
\label{whatever_de}
\ref{whatever_de}
\autoref{whatever_de}
Supuestos para las pruebas
Dados los siguientes archivos:
da/myfile_da.tex
de/myfile_de.tex
el/myfile_el.tex
en/myfile_en.tex
y cada archivo contiene:
\label{some_nice_thing}
\ref{some_nice_thing}
\autoref{some_nice_thing}
Mi acercamiento
Puedo usar nombres de carpetas como mis códigos ISO 639 y crear un bucle simple a través de los archivos. Lo siguiente simplemente debería imprimir las líneas modificadas en la consola del terminal. Intentaré explicar los resultados peculiares que obtengo con ejemplos:
Laboral:\\label\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\label\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
No funciona:\\ref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\ref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
No funciona:\\autoref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\autoref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Tenga en cuenta que grep -Pr
funciona con cada caso (eliminando grupos, por supuesto)
Respuesta1
\\
se convierte \
en comillas dobles. \\ref
se convierte \ref
en lo que de hecho es \r
seguido por ef
. Utilice cuatro barras invertidas:
for f in *; do
if [[ -d $f ]]; then
perl -ne "print if s/(\\\\ref\{.*?)\}/\1_$f\}/g" $f/SystemRequirements_$f.tex
fi
done
De manera similar, \a
es el carácter BELL ( \x07
).
Respuesta2
Es un problema de cotización. Estás utilizando comillas dobles para la $f
variable, pero las comillas dobles también tienen otras implicaciones. En particular, permiten el escape de caracteres con barra invertida, lo que \\
ocurre \
cuando llega a Perl:
$ printf "%s\n" "print if s/(\\label\{.*?)\}/\1_$f\}/g"
print if s/(\label\{.*?)\}/\1_\}/g
Esto crea un problema con r
, porque \r
será visto como el carácter de retorno (verperlrebackslash
) - no coincidirá r
. Utilice comillas simples en su lugar, abriéndose solo para la variable:
$ printf "%s\n" 'print if s/(\\label\{.*?)\}/\1_'"$f"'\}/g'
print if s/(\\label\{.*?)\}/\1_\}/g