Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Re: Get Vowels from sentence

by graff (Chancellor)
on Jan 04, 2007 at 06:21 UTC ( #592883=note: print w/replies, xml ) Need Help??

in reply to Get Vowels from sentence

Assuming you start with this:
$_ = <<SENTENCE; There once was a doggy in the window. I went into the store and inquired about the price, the doggy was too nice to ever think twice, so now I have a doggy to care for. SENTENCE
The next statement will extract all the vowels and save each one as a separate element in the @vowels array ("y" is not counted as a vowel in this case):
my @vowels = ( /[aeiuo]/gi );
I get 53 vowels, total, counting both upper- and lowe-case (because of the "i" modifier after the regex). If you wanted to count "y" when it functions as a vowel (i.e. when it is not followed by another vowel), the regex would be like this:
my @vowels = ( /[aeiou]|y(?![aeiou])/gi );
I get 56 vowels that way. The "(?!...)" part is called a "zero-width negative-look-ahead assertion" (sounds scary, eh?), and you can look it up in the perlre man page.

By putting the "g" modifier on the regex ("match globally" -- i.e. find all occurrences of the pattern), and putting the whole thing in a list context (assigning to an array), all the matches are captured as array elements.

update: Some "grammar police" might insist that "y" can only function as a vowel when there is no other vowel either before or after it -- e.g. "y" is not a vowel in "clay" (just as "w" is not a vowel in "claw"). Still, it seems like it has to be a vowel in cases like "rhythm". Those who hold this position would make the regex like this:

my @vowels = ( /[aeiou]|(?<![aeiou])y(?![aeiou])/gi );
using "(?<!...)" -- the "zero-width negative-look-behind assertion". The "zero-width" feature means that they are not counted as part of the matched string -- the regex still only matches (and captures) a single character at a time, which is either one of "a e i o u" or else a "y" that satifies the zero-width assertions.

Replies are listed 'Best First'.
Re^2: Get Vowels from sentence
by tiny_tim (Sexton) on Jan 04, 2007 at 22:43 UTC
    Thank you. This is what i wanted to do.
Re^2: Get Vowels from sentence
by meappy (Initiate) on Jul 19, 2010 at 16:42 UTC
    Hi, digging up an old thread. Here's my version of when to use "an" or "a" before a word. Treats ura*, uga*, uni* as non-vowels. Honest and Hour have silent consonants. Have I missed out anything? Or is there a better way to do this?
    if ( $something =~ /^[aeiou]/i && $something !~ /(un|uga|ura)/i || $so +mething =~ /hour/i || something =~ /honest/i ) { # First letter of $something is a vowel $print = "an $something"; } else { $print = "a $something"; }
      The thread wasn't really about handling "a" vs. "an" correctly, but that's okay. As for your code snippet... apart from forgetting the "$" on the fourth mention of "something", there are some problems...

      Since your three "exceptional case" conditions are not anchored to be string-initial, they'll misfire on words like "aunt", "aura", "man-hour", "dishonest", etc. Also, after you fix the anchoring, don't forget that adjectives can occur between the indefinite article and the noun, and many adjectives can begin with "un" as a negative prefix -- e.g. if your code snippet is preceded by:

      $something = "untimely death";
      you will get Bad English ("a" instead of "an"). In fact, it's pretty hard to handle word-initial "u" -- consider "unanswered" vs. "unanimous", "uninformed" vs. "uniform", etc. (And folks may disagree about cases like "Ugandan", "Ugaritic" and even "Uruguayan".) And then there's all those words starting with "eur"... Unless you take the time to plug in a pronouncing dictionary, you'll just have to put up with some mistakes.

      Still, here's a stab that tries to handle most cases in a reasonable way -- note how it sets the initial "u" problem apart as a separate condition, allowing it to be more complicated all by itself. (This code can be run with target words as command-line args, but the subroutine is self-contained and easy to modularize.)

      #!/usr/bin/perl use strict; sub indef_article { local $_ = shift; my $article; if ( /^(e)?u(\w+)/i ) { my $e = $1; local $_ = $2; $article = ( $e or /^(?:nanim|ni(?!n)|[gr][aeu])/i ) ? "a" : " +an"; # assumes y-glide pronunciations for Uruguay, Uganda, etc. } else { $article = ( /^(?:[aeio]|ho(?:ur|nest))/i ) ? "an" : "a"; } return "$article $_"; } print indef_article( $_ ).$/ for ( @ARGV );