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

Can someone explain this crazy thing?

File1 content:

2010-03-11 18:26:42,431 DEBUG 5 System 172.22.2.120 (null) asdfasd fasfdsdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
asdf asdf asdf asdf asd fasd fasdf asdf asdf asdf as dfasdf

2010-03-11 18:26:42,431 DEBUG 9 System 172.22.2.120 (null)asdf asdf asdf asdf asdf asdf asdf asd fasdfaf as fasdf asdf asdf as df
asdf asdf adsf sdf asdf a fasdf asdf asdfdf af

2010-03-11 18:26:42,431 DEBUG 8 System 172.22.2.120 (null)asdf asdf asdf asdf asdf asdf asfasdfasf asf asdf asdf asdf
asd fasdf asdf asdf asdf asdf asdfasf asdf asdf

File2 content:

2010-03-11 18:26:42,759 8 (null) (null) (null) asdf asdf asdf asdf asfasdf asdf asdf asdf asdf asdf asdf
2010-03-11 18:26:42,759 5 (null) (null) (null) asdf as fasdf asdf asdf as fasdf asdf asdfasdf
2010-03-11 18:26:42,759 1 (null) (null) (null) asf asf asdf asdf asdfasdfasdfas df asdf

I want to read the file line by line but 1 line has to be the stuff between the dates in both files. So I thought it would be great to use $/ to make Perl read kind of line I want:
open F, $file; $/ =  m/\d{4}\-\d{2}\-\d{2}\s+\d{1,2}\:\d{1,2}\:\d{1,2}/; while (<F>){# my lines go here one by one! } It works for the first file but not for the second as when processing the second file with this code Perl treats all file as one line.
However when I change the code:
open F, $file; $/ ==  m/\d{4}\-\d{2}\-\d{2}\s+\d{1,2}\:\d{1,2}\:\d{1,2}/; while (<F>){# my lines go here one by one! } it works for the second file but stops for the first one (only stuff after the date in the same line is read, but nothing in consecutive lines even if this is the same date). Is there a solution for both files? What Perl do with $/=value and $/==value ?

Replies are listed 'Best First'.
Re: PERL $/variable
by kennethk (Abbot) on Mar 11, 2010 at 18:36 UTC
    From $/ in perlvar:

    Remember: the value of $/ is a string, not a regex.

    The difference between your two 'assignment' statements is that the first one is actually an assignment (Assignment Operators) and the second is a logical test (Equality Operators). The result of the first is assigning $/ the result of a (probably) failed regular expression, which is "". The second is a test in void context, and thus does not change the value of $/ - it remains "\n". In short, it doesn't work that way and using warnings would have told you as much.

    Given that you've already constructed a regular expression, your easiest/fastest solution would be to slurp the files and use the regular expression in a while loop:

    #!/usr/bin/perl use strict; use warnings; local $/; $_ = <DATA>; while (m/(.+?(?:$|(?=\d{4}\-\d{2}\-\d{2}\s+\d{1,2}\:\d{1,2}\:\d{1,2})) +)/gs) { print "START${1}END\n"; } __DATA__ 2010-03-11 18:26:42,431 DEBUG 5 System 172.22.2.120 (null) asdfasd fas +fdsdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf asd fasd fasdf asdf asdf asdf as dfasdf 2010-03-11 18:26:42,431 DEBUG 9 System 172.22.2.120 (null)asdf asdf as +df asdf asdf asdf asdf asd fasdfaf as fasdf asdf asdf as df asdf asdf adsf sdf asdf a fasdf asdf asdfdf af 2010-03-11 18:26:42,431 DEBUG 8 System 172.22.2.120 (null)asdf asdf as +df asdf asdf asdf asfasdfasf asf asdf asdf asdf asd fasdf asdf asdf asdf asdf asdfasf asdf asdf
Re: PERL $/variable
by Animator (Hermit) on Mar 11, 2010 at 18:23 UTC

    You really should enable warnings in your code...

    Your first example: $/ = m/\d..../;.
    What this really means: $/ = ($_ =~ m/\d..../);.
    That is: you are first doing a match on $_ with the regex m/\d.../ and then assign the result of the match to $/.

    Your second example: $/ == m/\d.../;.
    What this really means: my $foo = ($_ =~ m/\d..../);$/ == $foo;.
    That is: That is: you are first doing a match on $_ with the regex m/\d.../ and then comparing the result of the match with $/ in a void context. (=> useless comparison)

    What you want to do is not possible with $/. $/ has to be a string (or a reference to a integer). It can not be a regex.

    What you could do is set $/ to undef; then read from the file and then use: while ($data =~ m/\d.../g) { ... }

Re: PERL $/variable
by Fletch (Bishop) on Mar 11, 2010 at 18:24 UTC

    $/ doesn't work that way.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Well it worked for me until I realized suspicious solution with $/ = value. Still it does what I want for file 1 :)
        It works for file 1 because records are separated by multiple new lines. The regular expression returned "" and, as per the provided link ($/):

        Setting to "" will treat two or more consecutive empty lines as a single empty line.