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

This is kind of related to an ealier post. I've successfully deleted the line break, but then i end up with some extra spaces.EX:
<meta name="revision" content= "Mon, 05 Jul 2006 23:59:59 GMT"
So, I tired this... but it ignores my switch (3rd nested if)
#!C:\Perl\bin\perl.exe use strict; use File::Find; use File::Slurp; use Time::Local; print "\nRunning ... \n\n"; my $root = "C:/"; # use forward slash, you can use mapped drives. print "changing to $root\n"; chdir $root; my $no_switches=0; my $no_files=0; my @log = (); my $dir; # find (\&Wanted, "department", "managers", "mybranch", "mycity", "myi +nfo", "resources"); find (\&Wanted, "working"); #directories - comman delimited sub Wanted { print "*Processing: $root$File::Find::name \n"; if ($_ =~ /\.htm(l)?$/i) { open(xFILE, $_) or die "ERROR: couldn't open file"; my @file = <xFILE>; foreach my $line (@file) { close (xFILE); if ($line =~ m/<meta[\s\r\n\t]+name="revision"[\s\r\n\t]+conte +nt=[\n]+/i) { open(FILE, ">$_") or die "ERROR: Can't open $_"; chomp($line); if ($line =~ m/(<meta[\s\r\n\t]+name="revision"[\s\r\n\t]+c +ontent=)([\s]+)(.*>)/i) { my $newline = $1.$3; $line =~ s/$line/$newline/; print "Switched: $newline\n"; } print FILE "@file"; # @file array is entire file. close (FILE); print "file overwritten\n"; push @log,"$root$File::Find::name \n\n"; $no_switches++; } # end if } # end for loop $no_files++; } #end if matches filetype else { print "file type not processed\n\n"; } #add $_ if you want + to see URL of file not processed. } # end sub
Forget it... it's only 1 line after the chomp. I need to do 2 passes

Replies are listed 'Best First'.
Re: Remove line break, then remove spaces (resolved)
by graff (Chancellor) on Jan 21, 2007 at 07:18 UTC
    I posted an alternative version in your other thread on this topic, but since that was buried pretty deep, I'll make the same mistake you just made (pursuing the same problem in two different threads).

    To be honest, I think the logic in the code you've posted is whacked. You put  close xFILE inside your  foreach $line loop, as if the input file needs to be closed more than once (it doesn't), and then you open the output file inside that same foreach loop, as if you need to open an output file once for each line of text (you don't). Also, your ragged use of indentation makes it hard to figure out what's going on, and I really don't see how your code doing what you say it's supposed to be doing. And I don't understand your comment about needing to do two passes (you don't).

    Anyway, here's how I would approach the problem as originally stated (if I understood that correctly): for each file containing a line that matches a specific pattern, remove the trailing whitespace from that line so that the next line becomes appended to it. Actually, the version below is a little different from what I put in the other thread: it checks the line being appended, and removes any initial whitespace.

    sub Wanted { if ( !/\S\.html?$/i ) { warn "$root$File::Find::name skipped\n"; } elsif ( !open( IN, "<", $_ )) { warn "open for read failed on $root$File::Find::name : $!\n"; } else { my @lines = (); my $line; my altered = 0; while ( defined( $line = <IN> )) { if ( $line =~ /<meta\s+name="revision"\s+content=\s*$/i ) +{ $line =~ s/\s*$//; my $append = <IN>; $append =~ s/^\s+//; $line .= $append; $altered++; } push @lines, $line; } close IN; if ( $altered ) { open( OUT, ">", $_ ) or die "open for write failed on $root$File::Find::name : + $!\n"; print OUT @lines; ## NB: no need for quotes here close OUT; } warn "$root$File::Find::name finished with $altered changes\n" +; } }
    In terms of coding style and organization, note how the "if ... elsif ... else ..." conditions are ordered so that the simple "no-op" and simple failure cases are dealt/dispensed with first; the more complicated business is handled last; in general, a loop that handles the contents of a file does not need to include opening and closing operations on files (there are only a few very rare situations where this is not true).

    It's really a matter of organizing your ideas for what the script is supposed to do, so that the sequence of steps for the program will make sense when expressed in plain English (or whatever your native human language may be). Then, the perl code should be a direct reflection of that sequence. That's a large part of what makes perl such a nice programming language.

      yeah, believe it or not my way works. Although your way is much cleaner and only requires 1 pass. Thanks, I learned a few things from your code. I'm a perl newb. Thanks again