perlnoob
perlnoob

Reputation: 107

Perl, regex, extract data from a line

Im trying to extract part of a line with perl

use strict; 
use warnings;


# Set path for my.txt and extract datadir
my @myfile = "C:\backups\MySQL\my.txt";
my @datadir = "";

open READMYFILE, @myfile or die "Error, my.txt not found.\n";
    while (<READMYFILE>) {
        # Read file and extract DataDir path
        if (/C:\backups/gi) {
        push @datadir, $_;
        }
    }

# ensure the path was found
print @datadir . " \n";

Basically at first im trying to set the location of the my.txt file. Next im trying to read it and pull part of the line with regex. The error Im getting is:

Unrecognized escape \m passed through at 1130.pl line 17.

I took a look at How can I grab multiple lines after a matching line in Perl? to get an idea of how to read a file and match a line within it, however im not 100% sure I'm doing this right or in the best way. I also seem to produce the error:

Error, my.txt not found.

But the file does exist in the folder C:\backups\MySQL\

Upvotes: 0

Views: 1328

Answers (6)

Ryan Zachry
Ryan Zachry

Reputation: 171

Since there are several problems I'll put comments on the changes I've made in the code below.

use strict; 
use warnings;
# For pretty dumping of arrays and what not.
use Data::Dumper;

# Use single quotes so you don't have to worry about escaping '\'s.
# Use a scalar ($) instead of an array(@) for storing the string.
my $myfile = 'C:\backups\MySQL\my.txt';

# No need to initialize the array.
my @datadir;

# I believe using a scalar is preferred for file handles.
# $! will contain the error if we couldn't open the file.
open(my $readmyfile, $myfile) or die "error opening: $!";

while (<$readmyfile>) {
    # You must escape '\'s by doubling them.
    # If you are just testing to see if the line contains 'c:\backups' you do not
    # need /g for the regex. /g is for repeating matches
    if (/C:\\backups/i) {
        push(@datadir, $_);
    }
}

# Data::Dumper would be better for dumping the array for debugging.
# Dumper wants a reference to the array.
print Dumper(\@datadir);

Update:

If you're referring to the output from Data::Dumper, it's just there for a pretty representation of the array. If you need a specifically formatted output you'll have to code it. A start would be:

print "$_\n" for (@datadir);

Upvotes: 4

justintime
justintime

Reputation: 3631

As other people have said, part of the issue is using " " rather than ' ' type of quoting. I try always to use ' ' unless I know I need to include an escape or interpolate a variable. Here are a number of pitfalls

    use 5.10.0 ;
    use warnings ;

    say "file is c:\mydir" ;
    say "please pay $100 ";
    say "on VMS the system directory is sys$system" ;
    say "see you @5 ";

With double quotes

    Unrecognized escape \m passed through at (eval 1) line 2.
    Possible unintended interpolation of @5 in string at (eval 1) line 5.
    file is c:mydir
    Use of uninitialized value $100 in concatenation (.) or string at (eval 1) line 3.
    please pay
    Use of uninitialized value $system in concatenation (.) or string at (eval 1) line 4.
    on VMS the system directory is sys
    see you

With single quotes

    file is c:\mydir
    please pay $100
    on VMS the system directory is sys$system
    see you @5

Upvotes: 1

rayners
rayners

Reputation: 539

The file is not being found because you are passing an array to open when it's expecting a scalar, so I'd guess that the array is being evaluated in a scalar context instead of as a list so you're actually telling perl to try opening the file named '1' instead of your 'my.txt' file.

Try something like this instead:

my $a = 'filename';
open FH, $a or die "Error, could not open $a: $!";
...

Upvotes: 1

Alex
Alex

Reputation: 2726

Shouldn't you be using $myfile instead of @myfile? The latter gives you an array, and since you're referencing it in scalar context, it's getting dereferenced (so it's actually trying to open a "file" called something like ARRAY(0xdeadbeef) instead of the actual filename).

Upvotes: 1

Mark Rushakoff
Mark Rushakoff

Reputation: 258128

When Perl sees the string "C:\backups\MySQL\my.txt" it tries to parse any escape sequences, such as \n. But when it sees \m in \my.txt, it's an unrecognized escape sequence, hence the error.

One way to fix this is to properly escape your backslashes: "C:\\backups\\MySQL\\my.txt". Another way to fix this is to use single quotes instead of double quotes: 'C:\backups\MySQL\my.txt'. Yet another way is to use the q() construct: q(C:\backups\MySQL\my.txt).

Upvotes: 4

frankc
frankc

Reputation: 11473

Use forward slashes instead of backslahes

Upvotes: 1

Related Questions