Another take. This will discard the first word or fragment, unless the first word is a match.
#!/usr/bin/perl use strict; use warnings; die "No search terms supplied!" unless @ARGV; my @words = @ARGV; my $text; { local $/ = undef; $text = <DATA>; } my $regex = join ( "|", @words ); # Words to highlight my $expr = qr /(?i)($regex)/; # Compile regex my $glen = 20; # Characters before and after the en +d of match to grab. { no warnings 'uninitialized'; my ( $ls, $le, @results ); # $ls=prev span start, $le=prev span end +, @results, results destination # Markup any matches or exit block. last unless $text =~ s/\b($expr)\b/[$1]/gi; while ( $text =~ m/\b($expr)\b/sg or $le <= length ($text) ) { my ($ipos,$spos,$epos); # char span positions if ($ipos = pos($text)) { # If the last match succeded $spos = $ipos - $glen > 0 ? $ipos - $glen : 0; # Range +check $epos = $ipos + $glen < length($text) ? $ipos + $glen : length +($text); # Assign to ($ls,$le) if this is our first time through and ne +xt. ( $ls, $le ) = ( $spos, $epos ) and next unless $le; } if ( $spos and $spos < $le ) { # If we have a match and it inte +rsects the last match $le = $epos; # merge overlapping char spans } else { # Lose the first word(possible fragment) unless the match is t +he first word. $ls = index($text," ", $ls) + 1 unless ($ls == 0); push @results,substr( $text, $ls, $le - $ls ) ; ( $ls, $le ) = ( $spos, $epos ); # Set "las +t position" to current. } last unless defined $spos; # End unle +ss we have one more match } print '"',$_,'..."', "\n" foreach @results; } __DATA__ Regular expressions have always been a weak spot for me, and I've got +a question that's got me stumped. Here's the problem I'm trying to solv +e. I have somewhat large articles of text (returned from a search), what + I'd like to do is capture the word and X number of words before and after + it while tagging the matching word in the captured text. My inital thoug +ht was to try something like this. The problem I have is that if there i +s more than one term and they overlap, the nth term will not be annotat +ed. So my next thought is lookahead/lookbehind, but they don't capture. Is there a way to do this with a single regex? Is a regex even the be +st way to do this? Thanks, -Lee

-Lee

perl digital dash (in progress)

In reply to Re: Regex: Matching around a word(s) by shotgunefx
in thread Regex: Matching around a word(s) by shotgunefx

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.