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

Hi, I have been trying to get a regular expression to match over two lines. Here is my input data:

ghjghjgkhgkghj

-----

-----

fsgdfgsdfgdfsgdsfg

I would like the regular expression to match the two lines of "----" and convert them to one.

So that the result would be:

ghjghjgkhgkghj

-----

fsgdfgsdfgdfsgdsfg

I would also like it to convert multiple lines of ----- to 1 line.

I have tried :

s/-----\n-----/------/g

and many variations, but nothing has been successful. Thank You, Jeff

Replies are listed 'Best First'.
Re: Two line match
by moritz (Cardinal) on Mar 10, 2008 at 15:14 UTC
    s/-----\n-----/------/g or s/-----\n+-----/------/g both should work, but only if you have both lines in $_.

    If you read your files with a standard loop like this:

    while (<>)[ # substition here }
    it can never work, because there's only one line in $_ when you run the substition.
      I am trying to do it as a one-liner on the command line using

      cat foo.txt | perl -p -e 's/-----\n-----/------/g' and it does not do anything. Is there a problem with multiple lines and command-line matching? Jeff

        The -p option enables line-by-line processing, so you have to change perls notion of a line:

        perl -pe 'BEGIN { $/ = undef }; s/---\n---/---/g;'

        use -0 to read whole file at once:

        cat foo.txt | perl -p0 -e 's/-----\n\n-----/------/g'
Re: Two line match
by toolic (Bishop) on Mar 10, 2008 at 15:25 UTC
    #!/usr/bin/env perl use warnings; use strict; my $prev = 0; while (<DATA>) { if (/-----/) { print unless $prev; $prev = 1; } else { print; $prev = 0; } } __DATA__ aaaaaaaaaaaa ----- ----- bbbbbbbbbbbb ----- ----- ----- ccccccccccccc

    Prints:

    aaaaaaaaaaaa ----- bbbbbbbbbbbb ----- ccccccccccccc
      That works except that it only converts two lines of ----- into one. I wanted it to be able to convert any number of lines of

      -----

      ------

      ------> into 1 line of it. Shouldn't the /g do that? Jeff

        My code converts 2 consecutive lines of 5 dashes into one line of 5 dashes (between the line of "a"'s and the line of "b"'s).

        My code also converts 3 consecutive lines of 5 dashes into one line of 5 dashes (between the line of "b"'s and the line of "c"'s).

        You can add any arbitrary number of lines of 5 dashes, and they will all be converted to one line of 5 dashes.

        I guess I do not understand your question afterall.

Re: Two line match
by NetWallah (Canon) on Mar 10, 2008 at 16:07 UTC
    Here is a one-liner you can try. Interchange quotes(' vs ") if on Linux:
    perl -ne "next unless /ghjghjgkhgkghj/../fsgdfgsdfgdfsgdsfg/;chomp;pus +h @l,$_;END{$r=join '', @l[1..$#l-1];print $r}" Your-file-name-here
    Note the use of the flip-flop operator .. to select stuff between the tokens, and array slicing to avoid the delimiters.

         "As you get older three things happen. The first is your memory goes, and I can't remember the other two... " - Sir Norman Wisdom

      Thank you for all of the help
Re: Two line match
by olus (Curate) on Mar 10, 2008 at 15:15 UTC

    You have two line breaks between the '-----' lines, because you have an empty line in the middle (or so it seems). Your regexp should account for two \n and not only one.