2010-05-27 18 views
12

¿Hay alguna manera de reemplazar una cadena como @ o * o ? o & sin necesidad de poner una "\" antes?¿Cómo se escapan los caracteres especiales para una sustitución en un trazador de líneas Perl?

Ejemplo:

perl -pe 'next if /^#/; s/\@d\&/new_value/ if /param5/' test 

En este ejemplo tengo que sustituir un @d& con new_value pero el valor antiguo puede contener cualquier carácter, ¿cómo puedo escapar sólo los caracteres que deben ser escapado?

+0

http://stackoverflow.com/questions/576435/how-do-i-handle-special-characters- in-a-perl-regex – daxim

Respuesta

7

usted tiene varios problemas:

  1. está usando el \b incorrectamente
  2. Usted está reemplazando código con variables de shell
  3. Es necesario citar metacaracteres

De perldoc perlre

Un límite de palabra ("\ b") es un punto entre dos caracteres que tiene una "\ w" en un lado de ella

Ninguno de los personajes @ o & son \w caracteres. Por lo tanto, se garantiza que su partido fallará. Es posible que desee usar algo como s/(^|\s)\@d\&(\s|$)/${1}new text$2/

(^|\s) dice para igualar o bien el inicio de la cadena (^) o un carácter de espacio en blanco (\s).

(\s|$) dice que coincida con el final de la cadena ($) o un carácter de espacio en blanco (\s).

Para resolver el segundo problema, debe usar %ENV.

Para resolver el tercer problema, debe usar las secuencias de escape \Q and \E para escapar del valor en $ENV{a}.

Poniendo todo junto obtenemos:

#!/bin/bash 

export a='@d&' 
export b='new text' 

echo 'param5 @d&' | 
    perl -pe 'next if /^#/; s/(^|\s)\Q$ENV{a}\E(\s|$)/$1$ENV{b}$2/ if /param5/' 

que imprime

param5 new text 
+0

muy bueno por favor explique el (^ | \ s) segundo uso el archivo no por echo ..... como perl -i -pe ........ archivo necesito cambiar algo? – yael

+0

La opción '-p' tomará de STDIN o de una lista de archivos pasados ​​como argumentos, por lo que debería estar bien usarlo como estaba antes. Acabo de usar el eco para fines de demostración (me gustan los ejemplos autocontenidos). –

+0

entonces puedo usar cualquier char como & o% o $ o? o * como char sin ningún problema es el objetivo para reemplazar líneas muy grandes con uniq char en el archivo de texto waht U think? – yael

10

Como se discutió en perldoc perlre:

... Hoy en día es más común el uso de la función quotemeta() o el "\ Q" metaquoting secuencia de escape para desactivar todos los significados especiales metacaracteres como esto:

/$unquoted\Q$quoted\E$unquoted/ 

Tenga en cuenta que si se pone barras invertidas literales (los que no las variables dentro interpolados) entre "\ Q" y "\ e", backsl doble quotish la interpolación de cenizas puede dar lugar a resultados confusos. Si necesita utilizar barras invertidas literales dentro de "\ Q ... \ E", consulte "Detalles de Gory de construcciones analizadas en el análisis" en perlop.

también puede utilizar un ' como delimitador en el s /// operación para hacer que todo se va a analizar, literalmente:

my $text = '@'; 
$text =~ s'@'1'; 
print $text; 

En su ejemplo, se puede hacer (nota las comillas simples):

perl -pe 's/\b\[email protected]&\E\b/new_value/g if m/param5/ and not /^ *#/' 
+0

puede ser más específico con mi ejemplo: perl -pe "s/\ b \ Q @ f & \ E \ b/new_value/g si m/param5/y no/^ * #/" ¿Cómo lo cambio para reemplazar la @f & con new_value? – yael

+0

acerca de su última respuesta No trabajo con script perl mi script es bash así que no puedo usar la sintaxis de perl – yael

+0

@yael: el último ejemplo fue solo eso, un ejemplo. Puede hacer cualquier cosa con un perfilador de perl que pueda hacer con un guión real de perl, y de manera similar puede convertir cualquier perfilador de Perl en un guión real de perl (¡no hay nada de malo en los guiones cortos!) – Ether

6

las otras respuestas han cubierto la cuestión, ahora aquí está tu meta-problema: Leaning Toothpick Syndrome. Es cuando el delimitador y los escapes comienzan a difuminarse juntos:

s/\/foo\/bar\\/\/bar\/baz/ 

La solución es utilizar un delimitador diferente. Puede usar casi cualquier cosa, pero las llaves equilibradas funcionan mejor. La mayoría de los editores pueden analizarlos y, en general, no debes preocuparte por escapar.

s{/foo/bar\\}{/bar/baz} 

Aquí está su expresión regular con delimitadores apuntalados.

s{\@d\&}{new_value} 

Mucho más fácil en los agujeros de ojo.

+0

Nunca había oído hablar del síndrome de palillo de dientes. Es genial que haya un nombre para este inconveniente: siempre uso llaves en lugar de barras. También acuñé el término "maven diarrea" para todos los resultados inútiles de los comandos mvn de salida. Espero que ese término se conozca. –

1

Si realmente desea evitar escribir el \ s, coloque su cadena de búsqueda en una variable y luego en su expresión regular. No necesita quotemeta o \Q ... \E en ese caso. Por ejemplo:

my $s = '@d&'; 
s/$s/new_value/g; 

Si tiene que usar esto en una sola línea, tenga en cuenta que tendrá que escapar de las $ s si se utiliza "s para contener el código Perl, o escapar de las ' s si usa ' s para contener su código perl.

+0

Probablemente quiso decir: s/\ Q $ s \ E/new_value/g; –

Cuestiones relacionadas