sharksfan98
sharksfan98

Reputation: 567

Printing the words matched by a regular expression

Ok, I'm going a simple Perl 5 Script that prints out words that begin with D and end with E...

$_ = "Dog Die Do Dome";
/^d.*e$/i;

As shown, I used Regular Expressions to search through my text to find such words, but how to I print them out? Thank in advance for any help.

Upvotes: 0

Views: 154

Answers (5)

Vijay
Vijay

Reputation: 67211

>cat temp
Dog Die Do Dome
>perl -lne '@a=split" ";foreach(@a){print if(/^[dD].*[eE]$/)}' temp
Die
Dome

Upvotes: 1

David W.
David W.

Reputation: 107040

First thing is that your regular expression is capturing your entire string. Regular expressions are normally greedy, so the .* will match the longest part of the string that's true. Since your regular expression begins with a d and ends with an e, it will match your whole string.

There are several ways you could avoid this:

my $string = "Dog Die Do Dome";
my $string =~ /d[\S]+e/ig;

Since \S says no white space, you are only matching the words that begin with a D and end with an E and contain no white space. Thus, it will now match Die and Domeseparately, but not Dog and Do. This is a common trick in regular expressions. For example, you have a string foo-bar-bam, and only want to match the first word. Using /[^-][^-]*/ will do the trick (remember that * can stand for zero or more of the preceding. Thus, you double it up to match at least one.). This is mainly used in older versions of grep or sed where you don't have the power of Perl's expanded regualar expressions. In my example above, I used + instead of * because + means match one or more of the preceding.

Perl also has a way to make a Regular expression non-greedy by using appending a question mark after the * or +:

my $string =~ /d.+?e/ig;

However, in your case, this would match Dog Die and Dome which is probably not what you want.

Here's the program:

use strict;
use warnings;
use feature qw(say);

my $string = "Dog Die Do Dome";

my @matches = ($string =~ /D\S+e/gi);

for my $word (@matches) {
    say "The first match is $word";
}

And, it prints out:

 The first match is Die
 The first match is Dome

Okay, maybe I shouldn't use The first match, but you get the idea. Try this sample program with various regular expressions and see what happens.

Upvotes: 2

DJG
DJG

Reputation: 6543

  1 
  2 my $word_list = "Dog Die Do Dome";
  3 my @words = split ' ', $word_list;
  4 for my $word (@words) {
  5         print "$word\n" if $word =~ /^d.*e$/i;
  6     }
~            

~
~
~

Upvotes: 0

TLP
TLP

Reputation: 67900

You can capture to an array, using the /g modifier.

use feature 'say';
my @words = /\bd\S+e\b/ig;
say for @words;

In list context, this will return all matches which start with a "d" and ends with an "e". Note that you cannot use .* because that match is greedy, so "dog do die" will return the entire string dog do die with a greedy match, and not just "die". Using the word boundary \b will prevent you from matching partially, such as with foobaresk.

Upvotes: 4

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84343

Use the print Statement

You use the print statement to send output to the screen. Since you are matching entire lines, you don't have to do anything complex here; you can just use the implied $_ variable. For example:

print if /^d.*e$/i

Upvotes: 1

Related Questions