Utilizzando Perl, come posso mostrare il contesto attorno a un termine di ricerca nei risultati di ricerca?

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

  •  03-07-2019
  •  | 
  •  

Domanda

Sto scrivendo uno script Perl che sta cercando un termine in grandi parti di testo. Quello che vorrei visualizzare all'utente è un piccolo sottoinsieme del testo attorno al termine di ricerca, in modo che l'utente possa avere un contesto in cui viene utilizzato questo termine di ricerca. I risultati di ricerca di Google sono un buon esempio di ciò che sto cercando di realizzare, in cui il contesto del termine di ricerca viene visualizzato sotto il titolo del link.

La mia ricerca di base sta usando questo:

if ($text =~ /$search/i ) {
    print "${title}:${text}\n";
}

($ title contiene il titolo dell'elemento in cui è stato trovato il termine di ricerca) Questo è troppo, dato che a volte $ text conterrà centinaia di righe di testo.

Questo verrà visualizzato sul Web, quindi potrei semplicemente fornire il titolo come un link al testo reale, ma non c'è contesto per l'utente.

Ho provato a modificare il mio regex per catturare 4 parole prima e 4 parole dopo il termine di ricerca, ma ho riscontrato problemi se il termine di ricerca era all'inizio o alla fine di $ text.

Quale sarebbe un buon modo per raggiungere questo obiettivo? Ho provato a cercare CPAN perché sono sicuro che qualcuno abbia un modulo per questo, ma non riesco a pensare ai termini giusti da cercare. mi piacerebbe farlo senza moduli, se possibile, perché ottenere moduli installati qui è una seccatura. Qualcuno ha qualche idea?

È stato utile?

Soluzione

Il tuo tentativo iniziale di 4 parole prima / dopo non era troppo lontano.

Prova:

if ($text =~ /((\S+\s+){0,4})($search)((\s+\S+){0,4})/i) {
    my ($pre, $match, $post) = ($1, $3, $4);
    ...
}

Altri suggerimenti

Puoi usare $ e $ 'per ottenere la stringa prima e dopo la partita. Quindi troncare tali valori in modo appropriato. Ma come sottolinea blixtor, shlomif ha ragione a suggerire di usare @ + e @ - per evitare la penalità prestazionale imposta da $ e # '-

$foo =~ /(match)/;

my $match = $1;
#my $before = 

Puoi usare $ e $ 'per ottenere la stringa prima e dopo la partita. Quindi troncare tali valori in modo appropriato. Ma come sottolinea blixtor, shlomif ha ragione a suggerire di usare @ + e @ - per evitare la penalità prestazionale imposta da $ e # '-

; #my $after = ; my $before = substr($foo, 0, $-[0]); my $after = substr($foo, <*>[0]); $after =~ s/((?:(?:\w+)(?:\W+)){4}).*/$1/; $before = reverse $before; # reverse the string to limit backtracking. $before =~ s/((?:(?:\W+)(?:\w+)){4}).*/$1/; $before = reverse $before; print "$before -> $match <- $after\n";

Suggerirei di usare i parametri posizionali - @ + e @ - (vedi perldoc perlvar) per trovare la posizione nella stringa della corrispondenza e quanto ci vuole.

Potresti provare quanto segue:

if ($text =~ /(.*)$search(.*)/i ) {

  my @before_words = split ' ', $1;
  my @after_words = split ' ',$2;

  my $before_str = get_last_x_words_from_array(@before_words);
  my $after_str = get_first_x_words_from_array(@after_words); 

  print $before_str . ' ' . $search . ' ' . $after_str;

}

Alcuni codici ovviamente sono stati omessi, ma questo dovrebbe darti un'idea dell'approccio.

Per quanto riguarda l'estrazione del titolo ... Penso che questo approccio non si presti molto bene a questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top