Come posso conservare gli spazi bianchi quando abbino e sostituisco più parole in Perl?
-
07-07-2019 - |
Domanda
Diciamo che ho del testo originale:
here is some text that has a substring that I'm interested in embedded in it.
Ho bisogno che il testo corrisponda a una parte di esso, ad esempio: " ha una sottostringa
" ;.
Tuttavia, il testo originale e la stringa corrispondente potrebbero presentare differenze di spazio. Ad esempio, il testo della corrispondenza potrebbe essere:
has a substring
o
has a substring
e / o il testo originale potrebbe essere:
here is some text that has a substring that I'm interested in embedded in it.
Ciò di cui ho bisogno per l'output del mio programma è:
here is some text that [match starts here]has a substring[match ends here] that I'm interested in embedded in it.
Devo anche preservare il motivo degli spazi bianchi nell'originale e aggiungere solo i marcatori di inizio e fine.
Qualche idea su come usare le regex del Perl per far sì che ciò accada? Ci ho provato, ma alla fine mi sono confuso orribilmente.
Soluzione
È passato del tempo da quando ho usato le espressioni regolari perl, ma che dire di:
$match = s/(has\s+a\s+substring)/[$1]/ig
Questo catturerebbe zero o più spazi bianchi e nuovi caratteri tra le parole. Avvolgerà l'intera partita con parentesi mantenendo la separazione originale. Non è automatico, ma funziona.
Puoi giocare con questo, come prendere la stringa " ha una sottostringa "
e fare una trasformazione su di essa per renderla " ha \ s * a \ s * sottostringa " ;
per renderlo un po 'meno doloroso.
MODIFICA : incorporati commenti di ysth secondo cui il metacarattere corrisponde alle nuove righe e modifica le correzioni per il mio utilizzo.
Altri suggerimenti
Questo modello corrisponderà alla stringa che stai cercando di trovare:
(has\s+a\s+substring)
Quindi, quando l'utente inserisce una stringa di ricerca, sostituisci qualsiasi spazio bianco nella stringa di ricerca con \ s +
e avrai il tuo modello. Sostituisci ogni corrispondenza con [la partita inizia qui] $ 1 [la partita finisce qui]
dove $ 1
è il testo corrispondente.
Nei regex, puoi usare +
per indicare "uno o più." Quindi qualcosa del genere
/has\s+a\s+substring/
corrisponde a ha
seguito da uno o più caratteri di spazi bianchi, seguito da a
seguito da uno o più caratteri di spazi bianchi, seguito da sottostringa
.
Mettendolo insieme a un operatore di sostituzione, puoi 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;
E l'output è:
here is some text that [match starts here]has a substring[match ends here] that I'm interested in embedded in it.
Molti hanno suggerito di usare \ s +
per abbinare gli spazi bianchi. Ecco come lo fai automaticamente:
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;
Output:
ecco alcuni testi che [la partita inizia qui] ha una sottostringa [la partita finisce qui] che mi interessa incorporare in esso.
Potresti voler sfuggire a qualsiasi meta-carattere nella stringa. Se qualcuno è interessato, potrei aggiungerlo.
Questo è un esempio di come potresti farlo.
#! /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/;
}
Questo attualmente fa di tutto per controllare la variabile $ match
per caratteri non sicuri.