Search code examples
perlstringmultilinefilehandle

How can I process a multi line string one line at a time in perl with use strict in place?


I'm trying to figure out the proper PBP approved way to process a multi line string one line at a time. Many Perl coders suggest treating the multi line string as a filehandle, which works fine unless you have "use strict" in your script. Then you get a warning from the compiler about not being able to use a string as a symbol while strict refs is in use.

Here's a simple working example of the problem:

#use strict;
use warnings; 

my $return = `dir`;
my $ResultsHandle = "";
my $matchLines = "";
my $resultLine = "";
open $ResultsHandle, '<', \$return;
while (defined ($resultLine = <$ResultsHandle>)) {
    if ($resultLine =~ m/joe/) {
        $matchLines = $matchLines . "\t" . $resultLine;
    }
}
close($ResultsHandle);
print "Original string: \n$return\n";
print "Found these matching lines: \n$matchLines\n";

Notice that the "use strict" line is commented out. When I run this script without use strict, I get what I want and expect:

Original string: 
 Volume in drive D has no label.
 Volume Serial Number is 50D3-54A6

 Directory of D:\Documents and Settings\username\My Documents\Eclipse\myTestProject

09/18/2009  11:38 AM    <DIR>          .
09/18/2009  11:38 AM    <DIR>          ..
09/18/2009  11:36 AM               394 .project
09/18/2009  11:37 AM                 0 joe.txt
09/18/2009  11:37 AM                 0 joey.txt
09/18/2009  11:38 AM                 0 kurt.txt
09/18/2009  11:43 AM               497 main.pl
09/18/2009  11:38 AM                 0 shane.txt
               6 File(s)            891 bytes
               2 Dir(s)   6,656,188,416 bytes free

Found these matching lines: 
    09/18/2009  11:37 AM                 0 joe.txt
    09/18/2009  11:37 AM                 0 joey.txt

Here's the problem, though. When I uncomment the "use strict" line, I get the following warning or error from Perl:

Can't use string ("") as a symbol ref while "strict refs" in use at D:/Documents and Settings/username/My Documents/Eclipse/myTestProject/main.pl line 8.

Line 8 is the "open $ResultsHandle, '<', \$return;" line, by the way. So since Perl Best Practices requires me to use strict, how does PBP expect me to process a multi line string one line at a time? Any suggestions from the SO community?

Thanks!


Solution

  • Don't initialise $ResultsHandle:

    use strict;
    use warnings; 
    
    my $return = `dir`;
    my $ResultsHandle;  # <-- leave undefined
    my $matchLines = "";
    my $resultLine = "";
    open $ResultsHandle, '<', \$return;
    while (defined ($resultLine = <$ResultsHandle>)) {
        if ($resultLine =~ m/joe/) {
            $matchLines = $matchLines . "\t" . $resultLine;
        }
    }
    close($ResultsHandle);
    print "Original string: \n$return\n";
    print "Found these matching lines: \n$matchLines\n";
    

    If you leave $ResultsHandle undefined before the open(), it will be filled in with a reference to the file handle. Because you were setting it to a string, open() presumed that it was supposed to be a symbolic reference to a variable instead --- not allowed under use strict.