
Estou usando Perl para analisar muitos arquivos de texto multilíngues. Preciso alterar o texto entre dois padrões:
Mudanças desejadas
Por exemplo, a versão original em inglês é assim:
\label{whatever}
\ref{whatever}
\autoref{whatever}
mas o material entre {
e }
deve ser sufixado com o código de idioma ISO 639 apropriado, por exemplo
\label{whatever_de}
\ref{whatever_de}
\autoref{whatever_de}
Suposições para teste
Dados os seguintes arquivos:
da/myfile_da.tex
de/myfile_de.tex
el/myfile_el.tex
en/myfile_en.tex
e cada arquivo contém:
\label{some_nice_thing}
\ref{some_nice_thing}
\autoref{some_nice_thing}
Minha abordagem
Posso usar nomes de pastas como meus códigos ISO 639 e criar um loop simples pelos arquivos. O seguinte deve simplesmente imprimir as linhas alteradas no console do terminal. Tentarei explicar os resultados peculiares que estou obtendo através de exemplos:
Trabalhando:\\label\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\label\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Não está funcionando:\\ref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\ref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Não está funcionando:\\autoref\{.*?\}
for f in *; do if [[ -d $f ]]; then perl -ne "print if s/(\\autoref\{.*?)\}/\1_$f\}/g" $f/myfile_$f.tex; fi; done
Observe que grep -Pr
funciona com cada caso (removendo grupos, é claro)
Responder1
\\
fica \
entre aspas duplas. \\ref
torna-se \ref
o que é de fato \r
seguido por ef
. Use quatro 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
Da mesma forma, \a
é o caractere BELL ( \x07
).
Responder2
É um problema de cotação. Você está usando aspas duplas para a $f
variável, mas aspas duplas também têm outras implicações. Em particular, eles permitem o escape de caracteres com barra invertida, o que \\
acontece \
quando chega ao Perl:
$ printf "%s\n" "print if s/(\\label\{.*?)\}/\1_$f\}/g"
print if s/(\label\{.*?)\}/\1_\}/g
Isso cria um problema com r
, porque \r
será visto como o caractere de retorno (vejaperlrebackslash
) - não corresponderá r
. Use aspas simples, abrindo apenas para a variável:
$ printf "%s\n" 'print if s/(\\label\{.*?)\}/\1_'"$f"'\}/g'
print if s/(\\label\{.*?)\}/\1_\}/g