-9

Cross-posted at Perlmonks

$String = "hello I went to the store yesterday and the day after and the day after";

I only want to print the words i went to the store. I tried two ways, neither worked:

if ($String =~ /hello/i) {
    until ($String =~ /yesterday/i) {
        print "Summary: $'"
    }
}

This printed the entire string. I used the $' function, but it took too much data. How do I limit it?

What if I wanted to print only "yesterday and the day after"? How would I be able to start matching the script in the middle?

daxim
  • 39,270
  • 4
  • 65
  • 132
Miriam Herm
  • 62
  • 1
  • 7
  • 2
    You should be able to augment this old question to suit your needs: http://stackoverflow.com/questions/11084106/how-to-copy-a-pattern-from-a-string-variable-in-perl/11084290#11084290 – PinkElephantsOnParade Jun 18 '12 at 18:43
  • `yesterday and the day after` What exactly are you trying to do? –  Jun 18 '12 at 19:35

4 Answers4

1

First, previous answers use $1, but I hate using global variables when it's not necessary. It's not necessary here.

Second, previous answers assume you don't want to capture newlines, but you didn't say anything of the kind.

Fix:

if (my ($match) = $s =~ /hello (.*?) yesterday/s) {
   say $match;
}

Finally, using the ? greediness modifier can lead to surprises (especially if you use more than one in a single pattern). If given

hello foo hello bar yesterday

the above regex will capture

foo hello bar

If you want

bar

use the following instead:

if (my ($match) = $s =~ /hello ((?:(?!yesterday).)*) yesterday/s) {
   say $match;
}

(?:(?!STRING).) is to STRING as [^CHAR] is to CHAR.

ikegami
  • 367,544
  • 15
  • 269
  • 518
1

This answers the original question and the follow-up.

use strict;
use warnings FATAL => 'all';
my $String = 'hello I went to the store yesterday and the day after and the day after';
my ($who_what_where) = $String =~ /hello (.*) yesterday/;
# 'I went to the store'

Matching the middle of a string is the default behaviour, it is no different from the first example.

my ($when) = $String =~ /store (.*) and/;
# 'yesterday and the day after'

I do not recommend the use of $1, $` to beginners, it is often problematic, see Perl: Why doesn't eval '/(...)/' set $1? and Perl doesn't update to next match for recent examples how it can go wrong easily in more complex programs. Instead I teach to simply use the return value of the match operation, it does not have the drawbacks of $1, $` and friends.

Community
  • 1
  • 1
daxim
  • 39,270
  • 4
  • 65
  • 132
0

Here's a start.

if ($String =~ /hello (.*?) yesterday/i) {
    print $1;
}
Andrew Cheong
  • 29,362
  • 15
  • 90
  • 145
0

You capture text by using parentheses () and $1 ($2 for second parentheses group, etc).

use strict;
use warnings;  # always use these 

my $string= "hello I went to the store yesterday and the day after " ;

if (/hello (.*?) yesterday/i) {
    print "Summary: $1\n";
}
TLP
  • 66,756
  • 10
  • 92
  • 149