Por que o regex perl encontra o padrão \\ label \ {. *? \} mas não \\ ref. *? \} ou \\ autoref \ {. *? \} em TeX Files?

1

Estou usando o perl para analisar muitos arquivos de texto multilíngües. Preciso alterar o texto entre dois padrões:

Alterações 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 testes

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

Eu posso usar nomes de pastas como meus códigos ISO 639 e criar um loop simples através dos arquivos. O seguinte deve simplesmente imprimir as linhas alteradas para o console do terminal. Vou tentar explicar os resultados peculiares que estou obtendo pelo exemplo:

Trabalhando: \label\{.*?\}

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

Não funciona: \ref\{.*?\}

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

Não funciona: \autoref\{.*?\}

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

Observe que grep -Pr funciona com cada caso (removendo grupos, é claro)

    
por Jonathan Komar 17.02.2016 / 22:10

2 respostas

2

É um problema de citação. Você está usando aspas duplas para a variável $f , mas as aspas duplas também têm outras implicações. Em particular, eles permitem o escape de caracteres em barra invertida, portanto, \ se torna \ quando atinge Perl:

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

Isso cria um problema com r , porque \r será visto como o caractere de retorno (consulte perlrebackslash ) - não corresponderá a r . Use aspas simples, abrindo apenas para a variável:

$ printf "%s\n" 'print if s/(\label\{.*?)\}/_'"$f"'\}/g'
print if s/(\label\{.*?)\}/_\}/g
    
por 17.02.2016 / 22:19
4

\ torna-se \ entre aspas duplas. \ref se torna \ref , que é, na verdade, \r seguido por ef . Use quatro barras invertidas:

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

Da mesma forma, \a é o caractere BELL ( \x07 ).

    
por 17.02.2016 / 22:23