2011-09-26 5 views
5

Estoy teniendo problemas con una referencia en mi texto de reemplazo que es seguido por un literal. He intentado lo siguiente:En perl, retro-referencia en el texto de reemplazo seguido de literal numérico

perl -0pi -e "s/(<tag1>foo<\/tag1>\n\s*<tag2>)[^\n]*(<\/tag2>)/\1${varWithLeadingNumber}\2/" file.xml 
perl -0pi -e "s/(<tag1>foo<\/tag1>\n\s*<tag2>)[^\n]*(<\/tag2>)/\g{1}${varWithLeadingNumber}\g{2}/" file.xml 

El primero, por supuesto, causa problemas debido a $ {} varWithLeadingNumber comienza con un número, pero pensé que el constructo \g{1} en mi segundo intento anterior se supone que resolver este problema. Estoy usando Perl 5.12.4.

+4

¿Estás seguro de que tu problema no está en el caparazón? Adjuntaría el guión entre comillas simples, excepto la parte que recoge las variables del intérprete de órdenes, solo para reducir la cantidad de barras invertidas de las que preocuparse. –

+0

Acabo de probar, por ejemplo, 'perl -0pi -e 's/( foo <\/tag1> \ n \ s * ) [^ \ n] * (<\/tag2>)/\ g {1} 25 \ g {2}/'file.xml', y el resultado fue el mismo. El texto de reemplazo termina siendo 'g {1} 25g {2}'. – jonderry

Respuesta

18

Usando \1, \2, etc. en la expresión de reemplazo está mal. \1 es un patrón de expresión regular que significa "hacer coincidir lo que coincidió con la primera captura", lo que no tiene sentido en una expresión de reemplazo. Los patrones de expresión regular no deben usarse fuera de las expresiones regulares. $1, $2, etc. es lo que debería usar allí.

Después de fijar \1, tiene

perl ... -e'... s/.../...$1$varWithLeadingNumber.../ ...' 

Dicho esto, creo que varWithLeadingNumber se supone que es una variable de shell? No deberías tener ningún problema si se trata de una variable de Perl. Si tiene la cáscara interpolar varWithLeadingNumber, el problema se puede solucionar utilizando

perl ... -e"... s/.../...\${1}${varWithLeadingNumber}.../ ..." 

nota que va a tener problemas si $ varWithLeadingNumber contiene "$", "@", "\" o "/", por lo Es posible que desee utilizar un argumento de línea de comando en lugar de interpolación.

perl ... -pe' 
    BEGIN { $val = shift; } 
    ... s/.../...$1$val.../ ... 
' "${varWithLeadingNumber}" 

También podría usar una variable de entorno.

export varWithLeadingNumber 
perl ... -pe's/.../...$1$ENV{varWithLeadingNumber}.../' 

o

varWithLeadingNumber=varWithLeadingNumber \ 
    perl ... -pe's/.../...$1$ENV{varWithLeadingNumber}.../' 

Si tenía un \1

s/...\1.../.../ 

se puede evitar el problema de varias maneras incluyendo

s/...(?:\1).../.../ 
+0

Esto funciona si hago 'perl -0pi-e 's/( foo <\/tag1> \ n \ s * ) [^ \ n] * (<\/tag2>)/$ {1}' $ {varWithLeadingNumber} '$ {2}/'archivo.xml. Gracias. – jonderry

+0

Solo para valores limitados de '$ varWithLeadingNumber'. Recomiendo contra eso. – ikegami

Cuestiones relacionadas