2010-04-19 12 views
7

Tengo un dolor de cabeza buscando esto: ¿Cómo se usa s /// en una expresión en lugar de una asignación. Para aclarar lo que quiero decir, yo estoy buscando un equivalente de Perl re.sub de pitón (...) cuando se utiliza en el siguiente contexto:¿Cómo puedo usar las // de Perl en una expresión?

newstring = re.sub('ab', 'cd', oldstring) 

La única manera que sé cómo hacer esto en perl hasta ahora es:

$oldstring =~ s/ab/cd/; 
$newstring = $oldstring; 

Tenga en cuenta la asignación adicional.

+4

Su ejemplo establecer tanto '$ oldstring 'y' $ newstring' al texto revisado. ¿Quería hacer la tarea antes de la sustitución y luego realizar la sustitución en '$ newstring'? – mob

Respuesta

7

Parece que tiene una idea falsa sobre cómo funciona =~. =~ es un operador vinculante que asocia una variable con un operador regexp. No hace ninguna asignación.

Todos los operadores de expresiones regulares funcionan por defecto con la variable de tema $_, por lo que s/foo/bar/; es lo mismo que $_ =~ s/foo/bar/;. No hay asignación. La variable de tema se transforma.

El caso es análogo cuando se opera con cualquier otra variable. $var =~ s/foo/bar/; transforma $var reemplazando la primera instancia de foo con bar. No hay asignación.

El mejor consejo que puedo darte es escribir Python en Python y Perl en Perl. No espere que los dos idiomas sean iguales.

Puede hacer como DVK sugiere y escribe una subrutina que reproducirá el comportamiento de sustitución al que está acostumbrado.

O podría intentar un Perl idiomático.En función de su deseo expreso de aplicar transformaciones múltiples en una línea, he proporcionado algunos ejemplos que pueden serle útiles.

Aquí, he utilizado un bucle for más de un elemento a tematizar $var y aplicar muchas transformaciones no modificables:

for($var) { 
    s/foo/bar/; 
    s/fizz/buzz/; 
    s/whop/bop-a-loo-bop/; 
    s/parkay/butter/; 
    s/cow/burger/; 
} 

O tal vez es necesario aplicar un grupo de variables de transformaciones. Defino una subrutina para recorrer una lista de referencias de matriz que definen pares de transformación antiguos/nuevos. Este ejemplo aprovecha el procesamiento de argumentos orientado a listas de Perl para manejar cualquier cantidad de transformaciones.

my $foo = transform(
    'abcd' => 
    [ 'a', 'b' ], 
    [ 'bb', 'c' ], 
    [ 'cc', 'd' ], 
    [ 'dd', 'DONE' ], 
); 

sub transform { 
    my $var = shift; 
    for (@_) { 
     my ($old, $new) = @$_; 
     $var =~ s/$old/$new/; 
    } 

    return $var; 
} 

Por último, un poco de perder el tiempo para proporcionar una versión de transformar que modifica su primer argumento:

my $foo = 'abcd'; 

transform_in_place(
    $foo => 
    [ 'a', 'b' ], 
    [ 'bb', 'c' ], 
    [ 'cc', 'd' ], 
    [ 'dd', 'DONE' ], 
); 

print "$foo\n"; 

sub transform_in_place { 
    for my $i (1..$#_) { 
     my ($old, $new) = @{$_[$i]}; 
     $_[0] =~ s/$old/$new/; 
    } 
} 

Por mi propio proyecto que probablemente haría uso de una de las dos primeras opciones en función de la necesidades del problema particular.

11

Se puede utilizar para una ($new = $old) =~ s/whatever/whateverelse/; exactamente misma funcionalidad que busca:

use strict; 
my $old = "OLD"; 
my $new; 
($new = $old) =~ s/OLD/NEW/; 
print "old=$old, new=$new"; 

Produce:

old=OLD, new=NEW 

Exactamente lo que quieres

Si lo que buscas es una función , puede definir el suyo para evitar la asignación:

use strict; 
sub re_sub { 
    my ($find, $replace, $old) = @_; 
    my $new = $old; 
    $new =~ s/$find/$replace/; 
    return $new; 
} 

my $old = "ab"; 
my $new = re_sub('ab', 'cd', $old); 
print "new=$new\n"; 

Resultados en new=cd.

7

La sustitución de expresiones regulares de Perl siempre ocurre 'in situ'. Así que hay que copiar la cadena a una nueva variable y operar en la nueva variable:

(my $newstring = $oldstring) =~ s/ab/cd/; 
+1

Basado en esto, ¿es correcto suponer que * no puede * tener dos s /// en una línea, una que usa el resultado de la otra, sin asignaciones intermedias? – Mansour

+1

Si bien puede lograr eso agregando paréntesis y = ~ al final, no hay una sintaxis limpia para ello. –

2

¿Quieres tener $ newString ser el resultado de la sustitución, ¿verdad?

Algo como esto:

($newstring = $oldstring) =~ s/ab/cd; 

debería funcionar. La asignación establece $newstring a $oldstring y luego evalúa a $newstring, que es sobre lo que actúa la sustitución.

1

En base a esto, ¿es correcto suponer que no puede tener dos s /// en una línea, una que utiliza el resultado de la otra, sin asignaciones intermedias? - mikeY

Sí, usted está en lo correcto. Si desea aplicar varias sustituciones a la misma cadena que haría

$newstring = $oldstring ; 
    $newstring =~ s/ab/cd/ ; 
    $newstring =~ s/xx/yy/ ; 

El siguiente no funcionará porque s// devuelve el número de sustituciones de hecho, no la cadena modificada.

$newstring = $oldstring) =~ s/ab/cd/ =~ s/xx/yy/ ; 

En resumen, las operaciones de expresiones regulares de Perl son muy diferentes a Python, y se encontrará mejor tratando de aprender lo Perl hace desde cero en lugar de tratar de mapear conceptos de Python en Perl

Cuestiones relacionadas