damian has asked for the wisdom of the Perl Monks concerning the following question:

hi fella monks, i'm having trouble on modifying the searched pattern found from a file. for example i have search this pattern in an html file.  <% INCLUDE file1.txt %> and this is located somewhere in the middle of the html file. how will i be able to replace this searched pattern with something like  <% INCLUDE file2.txt %> here's a someple of my code... now don't blame me i'm a newbie.
$template = "index.txt"; $counter = "counter.txt"; $pos = 0; $found = 0; $num = 0; open (F1, "+>$template"); @idxlines = <F1>; close F1; foreach $lines (@idxlines) { if ($lines =~ /<% INCLUDE file2.txt %>/) { $found = 1; last; } $pos++; } open (F1, "+<$template"); open (CT, "$counter"); $num = <CT>; close CT; if ($num == 2) { $num = "1" } else { $num++ } open(CT, ">$counter"); print CT $num; close CT; $idxlines[$pos] = "<% INCLUDE file$num.txt %>"; print F1 $idxlines[$pos]; close F1;
i'm using the counter file to increment the file(num).txt. i don't know if i'm doing it right... please help me. thanks in advance.

Replies are listed 'Best First'.
Re: modifying the search pattern of a file.
by davorg (Chancellor) on Jul 13, 2000 at 14:26 UTC

    Here a few comments on your code that might help you fix your problem.

    1. You don't use strict or use warnings
    2. You don't check the return values from die
    3. Some of your open calls look a bit complex for what they do, for example the first one could be written open(F1, $template) || die;
    4. $num = "1" could be written $num = 1
    5. You seem to assume that your tag can appear anywhere in a line when you're searching for it, but when you replace it you assume that it takes up the whole line. Is this right?
    --
    <http://www.dave.org.uk>

    European Perl Conference - Sept 22/24 2000, ICA, London
    <http://www.yapc.org/Europe/>
Re: modifying the search pattern of a file.
by le (Friar) on Jul 13, 2000 at 14:39 UTC
    This is pretty untested. It should switch between file1.txt and file2.txt.
    open(FILE, $file) or die $!; @lines = <FILE>; close FILE; for ($i = 0; $i <= $#lines; $i++) { if ($lines[$i] =~ /<% INCLUDE file(\d+)\.txt %>/) { $num = $1; # UPDATE: # ok, the next line (original) is wrong, see replies # $num = $num == 1 ? 1 : 2; # We have to write it this way: $num = $num == 1 ? 2 : 1; $lines[$i] =~ s/<% INCLUDE file(\d+)\.txt %>/<% INCLUDE file$num\. +txt %>/; } else { next; } open(FILE, ">$file") or die $!; print FILE @lines; close FILE;
      I don't want to be picky, but shouldn't:

      $num = $num == 1 ? 1 : 2;

      be:

      $num = $num == 1 ? 2 : 1;

      ?

        Or perhaps:
        $num--; $num||= 2; or $num=$num%2 ? 2 : 1;

        Shamefully, --$num||=2; is not allowed.

        Of course, sorry... I was in a hurry.
Re: modifying the search pattern of a file.
by splinky (Hermit) on Jul 13, 2000 at 21:58 UTC
    Just have to throw in a one-liner here, since there are command-line switches for this very thing.

    perl -i -pe 's/(<% INCLUDE file)(1|2)(\.txt %>)/$1 . ($2 == 1 ? 2 : 1) + . $3/eg' index.txt

    *Woof*

Re: modifying the search pattern of a file.
by t0mas (Priest) on Jul 13, 2000 at 16:43 UTC
    How about:
    use strict; use warnings; my $template = "index.txt"; open (FILE,"$template") or die "Can't read from $template: $!"; my @file=<FILE>; close (FILE); open (FILE,">$template") or die "Can't write to $template: $!"; foreach (@file) { if (/<% INCLUDE file(1|2)\.txt %>/) { $1 == 1 ? s/<% INCLUDE file1\.txt %>/<% INCLUDE file2\.txt %>/ : s/<% INCLUDE file2\.txt %>/<% INCLUDE file1\.txt %>/; } print FILE; } close (FILE);


    /brother t0mas
RE: modifying the search pattern of a file. (short version)
by turnstep (Parson) on Jul 13, 2000 at 22:04 UTC

    Still seems a bit wordy. :)

    use strict; use warnings; my $template = "index.txt"; open(FILE, "+<$template") or die "Could not read $template: $!\n"; local $/=""; ## Or even chop $/; !!! s#(<% INCLUDE file)(1|2)(\.txt %>)#"$1".($2%2?"2":"1")."$3"#eg, $/ .= +$_ while <FILE>; seek(FILE,0,0); print FILE $/; close(FILE); exit;

    Some caveats: normally a truncate(FILE, tell(FILE)); would be in order before the close statement, but since we are replacing one character with another, we can not worry about it here. This is not necessarily the best way to do this, nor the safest, nor the most portable, but it is short and hopefully someone will learn something from this other way of doing it.

    And, yes, it could easily become a command-line perl -e as well. :)