Saltar al contenido

Sustitución de expresiones regulares de Perl usando parámetros externos

Solución:

Solución 1: String::Substitution

Usar String::Substitution paquete:

use String::Substitution qw(gsub_modify);

my $find = "some_(w+)_thing';
my $repl="no_$1_stuff";
my $text = "some_strange_thing";
gsub_modify($text, $find, $repl);
print $text,"n";

Solo la cadena de reemplazo interpola (término usado libremente) vars coincidentes numeradas (como $1 o ${12}). Consulte “interpolate_match_vars” para obtener más información.

Este módulo hace no guardar o interpolar $& para evitar la “considerable penalización de rendimiento” (ver perlvar).

Solucion 2: Data::Munge

Esta es una solución mencionada por Grinnz en los comentarios a continuación.

los Data::Munge se puede utilizar de la siguiente manera:

use Data::Munge;

my $find = qr/some_(w+)_thing/;
my $repl="no_$1_stuff";
my $text="some_strange_thing";
my $flags="g";
print replace($text, $find, $repl, $flags);
# => no_strange_stuff

Solución 3: una forma rápida y sucia (si el reemplazo no contiene comillas dobles y no se considera la seguridad)

DESCARGO DE RESPONSABILIDAD: Proporciono esta solución ya que este enfoque se puede encontrar en línea, pero sus advertencias no se explican. No lo use en producción.

Con este enfoque, no puede tener una cadena de reemplazo que incluya un " comillas dobles y, dado que esto equivale a dar acceso directo al código a quien esté escribiendo el archivo de configuración, no debe exponerse a los usuarios de la Web (como lo menciona Daniel Martin).

Puede utilizar el siguiente código:

#!/usr/bin/perl
my $match = qr"some_(w+)_thing";
my $repl=""no_$1_stuff"";
my $text = "some_strange_thing";
$text =~ s/$match/$repl/ee;
print "Result: $textn";

Ver demostración de IDEONE

Resultado:

Result: no_strange_stuff

Tienes que

  1. Declare el reemplazo en '"..."' así como $1 podría ser evaluado más tarde
  2. Usar /ee para forzar la doble evaluación de las variables en el reemplazo.

Un modificador disponible específicamente para buscar y reemplazar es el s///e modificador de evaluación. s///e trata el texto de reemplazo como código Perl, en lugar de una cadena entre comillas dobles. El valor que devuelve el código se sustituye por la subcadena coincidente. s///e es útil si necesita hacer un poco de cálculo en el proceso de reemplazo de texto.

Puedes usar qr para crear una instancia de patrón para la expresión regular (qr"some_(w+)_thing").

Esencialmente el mismo enfoque que la solución aceptada, pero mantuve las líneas iniciales iguales a las del enunciado del problema, ya que pensé que podría facilitar el encajar en más situaciones:

my $match = "some_(\w+)_thing";
my $repl = "no_$1_stuff";

my $qrmatch = qr($match);
my $code = $repl;

$code =~ s/([^"\]*)(["\])/$1\$2/g;
$code = qq["$code"];

if (!defined($code)) {
  die "Couldn't find appropriate quote marks";
}

my $text = "some_strange_thing";
$text =~ s/$qrmatch/$code/ee;
print "Result: $textn";

Tenga en cuenta que esto funciona sin importar lo que haya en $repl, mientras que la solución ingenua tiene problemas si $repl contiene un carácter de comillas dobles en sí mismo, o termina en una barra invertida.

Además, suponiendo que va a ejecutar las tres líneas al final (o algo así) en un bucle, asegúrese de no omitir el qr línea. Hará una gran diferencia en el rendimiento si omite el qr y solo usa s/$match/$code/ee.

Además, aunque no es tan trivial obtener la ejecución de código arbitrario con esta solución como lo es con la aceptada, no me sorprendería que aún fuera posible. En general, evitaría soluciones basadas en s///ee Si el $match o $repl provienen de usuarios que no son de confianza. (por ejemplo, no cree un servicio web a partir de esto)

Hacer este tipo de reemplazo de forma segura cuando $match y $repl son proporcionados por usuarios que no son de confianza. Debería hacerse una pregunta diferente si su caso de uso incluye eso.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *