Comment préserver les espaces lorsque je fais correspondre et remplace plusieurs mots en Perl?

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

  •  07-07-2019
  •  | 
  •  

Question

Disons que j'ai du texte original:

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

J'ai besoin que le texte corresponde à une partie de celui-ci, par exemple: " a une sous-chaîne ".

Toutefois, le texte d'origine et la chaîne correspondante peuvent comporter des différences d'espaces. Par exemple, le texte de correspondance pourrait être:

has a
substring

ou

has  a substring

et / ou le texte original pourrait être:

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

Ce que j'ai besoin de mon programme pour sortir est:

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

Je dois également conserver le motif d'espacement dans l'original et y ajouter les marqueurs de début et de fin.

Avez-vous des idées sur la façon d'utiliser les expressions rationnelles Perl pour que cela se produise? J'ai essayé, mais j'ai fini par être terriblement confus.

Était-ce utile?

La solution

Cela fait quelque temps que je n'ai pas utilisé d'expressions régulières Perl, mais qu'en est-il:

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

Ceci capturerait zéro ou plusieurs espaces et caractères de nouvelle ligne entre les mots. Il va envelopper la partie entière avec des supports tout en maintenant la séparation d'origine. Ce n'est pas automatique, mais ça marche.

Vous pouvez jouer à des jeux avec cela, comme prendre la chaîne "a une sous-chaîne" et la transformer pour la rendre "a \ s * a \ s * sous-chaîne". ; pour rendre cela un peu moins douloureux.

MODIFIER : les commentaires de ysth incorporés indiquent que le métacaractère correspond aux corrections de nouvelle ligne et de hobbs apportées à mon utilisation.

Autres conseils

Ce modèle correspond à la chaîne que vous recherchez:

(has\s+a\s+substring)

Ainsi, lorsque l'utilisateur entre une chaîne de recherche, remplacez les blancs de la chaîne de recherche par \ s + et vous obtenez votre modèle. Il suffit de remplacer chaque correspondance par [la correspondance commence ici] $ 1 [la correspondance se termine ici] $ 1 est le texte recherché.

Dans les expressions rationnelles, vous pouvez utiliser + pour signifier " un ou plusieurs. " Donc, quelque chose comme ça

/has\s+a\s+substring/

correspond a suivi d'un ou plusieurs caractères d'espacement, suivi de a suivi d'un ou de plusieurs caractères d'espacement, suivi de sous-chaîne .

En l'associant à un opérateur de substitution, vous pouvez dire:

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;

Et le résultat est:

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

Plusieurs personnes ont suggéré d'utiliser \ s + pour faire correspondre les espaces. Voici comment vous le faites automatiquement:

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;

Sortie:

  

voici un texte que [match commence ici] a une sous-chaîne [correspondance se termine ici] que je souhaite y incorporer.

Vous voudrez peut-être échapper aux méta-caractères de la chaîne. Si quelqu'un est intéressé, je pourrais l'ajouter.

Ceci est un exemple de la façon dont vous pourriez le faire.

#! /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/;
}

Cela ne fait actuellement rien pour vérifier la variable $ match à la recherche de caractères non sécurisés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top