in reply to pattern matching

If you are having problems with code that does substitution, then you need to actually include that code.

I've always done this type of replacement using something like this:

my %subs = ( word1 => 'replace word1 with this text', word2 => 'replace word2 with this test', ); while($document =~ s/\[(\w+)\]) { my $word = $1; my $rep = $subs{$word} || "!Unknown token: $word!"; $document =~ s/\[$word\]/$subs{$word}/smg; }

Replies are listed 'Best First'.
Re: Re: pattern matching
by fasteddie (Initiate) on Feb 25, 2003 at 18:46 UTC
    #!/usr/bin/perl -w %hash = (); open(FILE, "story.txt") || die ; #opens file story.txt while ( $story[$i++] = <FILE> ){ } #moves story.txt to @story close (FILE); #closes Story.txt foreach $list ( @story ) { @temp = split(/ /, $list); #puts word by word in @temp $i=0; while ($i <= $#temp) { $word=$temp[$i]; if ( $word =~ /^\[/ && $word =~ /$\]/) { if (! exists $hash { $word } ) { $auxiliary_word = $word; $auxiliary_word =~ tr/\[/ /; #removes front bracket $auxiliary_word =~ tr/\].,?/ /; #removes rear bracket & pu +nctuation $capitol = 0; if ($word =~ /^\[[A-Z]/) #checks for capitol letter { $capitol = 1; } Replace($word,$capitol); #function call to enter own word +s } } $i++; } } Print(); #print final madlib story #***************************************************************** sub Replace #user enters own words { print" Please enter a $auxiliary_word: "; $new_word = <STDIN>; if ($capitol == 1 ) { $new_word =~ s/(^[a-z]+)/\u$1/; #makes first letter capitol } chomp ( $new_word ); $hash { $word } = $new_word; #adds capitol letter t +o hash } #********************************************************************* sub Print #function to print new story { foreach $list ( @story ) { @temp = split(/ /, $list); $i=0; while ($i <= $#temp) { $word = $temp[$i]; if ($word =~ /^\[/ && $word =~ /$\]/) #if ( $word =~ m/\B[[A-Za-z]]/g) { $temp[$i] = $hash { $word }; } $i++; } $final = join(' ', @temp); #joins story together print $final; #prints new story } }
    Strangeness in Cars I once owned a [noun] that was [adjective] only when , in a [Make-of-car]. Some [plural-noun] thought, [adverb], that this was [another-adjective], but what did they [verb]. Anyway, now I am [comparative], and don't [verb] so much, even when in [make-of-car] cars. Do you think that's [another-adjective], or should I [strange-action-verb]?
      You can reduce the code quite a bit by playing to Perl's strengths. The quick way to load the story into an array (once you've opened the file) is
      my @story = <FILE>;
      You can reduce the amount of work you're doing to pull out bracketed words by doing
      foreach my $line ( @story ) { $line =~ s/\[([A-Za-z-]+)\]/Replace($1)/eg; }
      This replaces each bracketed work with whatever Replace() returns for that word. The /eg modifiers on the regular expression say to replace whatever is found with the results of executing (/e) the expression on the right-hand side, and to repeat this match "globally" (/g) across the target string. And, because $line is "aliased" to each row in @story, you don't need to make a second pass through @story.

      Then, to print the story

      print @story;
      Now, you've localized all of the interesting work to
      sub Replace { my $word = shift; ... }
      which I'll leave as an exercise.

      One (perhaps main) reason your script didn't work as intended can be found on this line:
      if ($word =~ /^\[/ && $word =~ /$\]/)
      I think you're trying to use the dollar sign in the second regex to mean "if the word ends with a close-square-bracket", but since the dollar sign there is supposed to mean "end of string", you're supposed to place it at the end of the pattern, like this:
      if ($word =~ /^\[/ && $word =~ /\]$/)
      But as others have pointed out, there is room for quite a few other improvements to the code...