¿Cómo puedo preservar los espacios en blanco cuando hago coincidir y reemplazar varias palabras en Perl?

StackOverflow https://stackoverflow.com/questions/1425023

  •  07-07-2019
  •  | 
  •  

Pregunta

Digamos que tengo texto original:

here is some text that has a substring that I'm interested in embedded in it.

Necesito que el texto coincida con una parte de él, diga: " tiene una subcadena " ;.

Sin embargo, el texto original y la cadena coincidente pueden tener diferencias de espacio en blanco. Por ejemplo, el texto del partido podría ser:

has a
substring

o

has  a substring

y / o el texto original podría ser:

here is some
text that has
a substring that I'm interested in embedded in it.

Lo que necesito para que mi programa salga es:

here is some text that [match starts here]has a substring[match ends here] that I'm interested in embedded in it.

También necesito preservar el patrón de espacios en blanco en el original y simplemente agregarle los marcadores de inicio y fin.

¿Alguna idea sobre una forma de usar expresiones regulares de Perl para que esto suceda? Lo intenté, pero terminé confundiéndome horriblemente.

¿Fue útil?

Solución

Ha pasado algún tiempo desde que he usado expresiones regulares perl, pero ¿qué pasa con:

$match = s/(has\s+a\s+substring)/[$1]/ig

Esto capturaría cero o más espacios en blanco y caracteres de nueva línea entre las palabras. Envolverá todo el partido con paréntesis mientras mantiene la separación original. No es automático, pero funciona.

Podrías jugar con esto, como tomar la cadena " tiene una subcadena " y hacer una transformación para que " tenga \ s * a \ s * subcadena " ; para hacer esto un poco menos doloroso.

EDITAR : se incorporaron los comentarios de ysth de que el metacarácter \ s coincide con las nuevas líneas y las correcciones de hobbs al uso de mi \ s.

Otros consejos

Este patrón coincidirá con la cadena que está buscando encontrar:

(has\s+a\s+substring)

Entonces, cuando el usuario ingresa una cadena de búsqueda, reemplace cualquier espacio en blanco en la cadena de búsqueda con \ s + y tendrá su patrón. El, simplemente reemplace cada coincidencia con [la coincidencia comienza aquí] $ 1 [la coincidencia termina aquí] donde $ 1 es el texto coincidente.

En expresiones regulares, puede usar + para significar "uno o más". Entonces algo como esto

/has\s+a\s+substring/

coincide con has seguido de uno o más caracteres de espacio en blanco, seguido de a seguido de uno o más caracteres de espacio en blanco, seguido de subcadena .

Al unirlo con un operador de sustitución, puede decir:

my $str = "here is some text that has     a  substring that I'm interested in embedded in it.";
$str =~ s/(has\s+a\s+substring)/\[match starts here]$1\[match ends here]/gs;

print $str;

Y el resultado es:

here is some text that [match starts here]has     a  substring[match ends here] that I'm interested in embedded in it.

Muchos han sugerido, use \ s + para hacer coincidir los espacios en blanco. Así es como lo haces automáticamente:

my $original = "here is some text that has a substring that I'm interested in embedded in it.";
my $search = "has a\nsubstring";

my $re = $search;
$re =~ s/\s+/\\s+/g;

$original =~ s/\b$re\b/[match starts here]<*>amp;[match ends here]/g;

print $original;

Salida:

  

aquí hay un texto que [la coincidencia comienza aquí] tiene una subcadena [la coincidencia termina aquí] que me interesa incluir en ella.

Es posible que desee escapar de los metacaracteres en la cadena. Si alguien está interesado, podría agregarlo.

Este es un ejemplo de cómo podría hacer eso.

#! /opt/perl/bin/perl
use strict;
use warnings;

my $submatch = "has a\nsubstring";

my $str = "
here is some
text that has
a substring that I'm interested in, embedded in it.
";

print substr_match($str, $submatch), "\n";

sub substr_match{
  my($string,$match) = @_;

  $match =~ s/\s+/\\s+/g;

  # This isn't safe the way it is now, you will need to sanitize $match
  $string =~ /\b$match\b/;
}

Esto actualmente hace cualquier cosa para verificar la variable $ match en busca de caracteres inseguros.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top